autotel-eventcatalog 15.0.0 → 16.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,52 @@
1
1
  # Changelog
2
2
 
3
+ ## 16.0.0
4
+
5
+ ### Patch Changes
6
+
7
+ - 0f518c6: Refresh dependencies to their latest minor and patch releases, most notably the
8
+ OpenTelemetry SDK (`0.220.x` → `0.221.x`, `2.9.x` → `2.10.x`).
9
+
10
+ Majors are deliberately held back for a separate change, including TypeScript 7,
11
+ pnpm 11, chalk 6, jsdom 30 and the ESLint toolchain.
12
+
13
+ - 0f518c6: Stop publishing source maps. Every package is roughly half the size it was.
14
+
15
+ Published output across all packages drops from 18.7 MiB to 7.9 MiB. Installing
16
+ `autotel` downloads 500 KiB gzipped instead of 1,130 KiB. Nothing about the
17
+ shipped JavaScript or type declarations changed.
18
+
19
+ Source maps were 55–65% of every package, because each source byte was emitted
20
+ four times: once as ESM, once as CJS, and again inside each format's map, which
21
+ embedded `sourcesContent`. They never reached a consumer's application bundle —
22
+ bundlers read maps and discard them — so the cost was pure install weight in
23
+ exchange for TypeScript stack traces under `node --enable-source-maps`.
24
+
25
+ Best-in-class TypeScript libraries do not make that trade. Of fourteen surveyed,
26
+ twelve publish no maps at all (zod, hono, pino, fastify, vitest, vite, rollup,
27
+ undici, commander, tsdown, react, astro), and not one publishes `.d.ts.map`.
28
+ The OpenTelemetry packages do ship maps at around 50% of their size, which is
29
+ the convention this repo had been following.
30
+
31
+ The `.d.ts.map` declaration maps were broken regardless: `sourcesContent: false`
32
+ with sources pointing at `../src/*.ts`, which `files` never published, so they
33
+ resolved to nothing on a consumer's machine.
34
+
35
+ Maps are still generated for local development. `tsconfig.json` keeps
36
+ `sourceMap` and `declarationMap` on; only `tsconfig.build.json` disables them,
37
+ so debugging the workspace is unchanged.
38
+
39
+ This also fixes the bundle-size gate, which had been amplifying every ordinary
40
+ change by 4×. The three packages that were failing it (`autotel-backends` +43.9%,
41
+ `autotel-mcp` +14.4%, `autotel-schema` +12.0%) were not bloated — that growth was
42
+ legitimate new backend code, quadrupled by the build. The baseline is
43
+ regenerated.
44
+
45
+ - Updated dependencies [0f518c6]
46
+ - Updated dependencies [0f518c6]
47
+ - Updated dependencies [0f518c6]
48
+ - autotel-subscribers@46.0.0
49
+
3
50
  ## 15.0.0
4
51
 
5
52
  ### Patch Changes
package/dist/cli.cjs CHANGED
@@ -433,5 +433,4 @@ main().catch((error) => {
433
433
  process.exit(1);
434
434
  });
435
435
 
436
- //#endregion
437
- //# sourceMappingURL=cli.cjs.map
436
+ //#endregion
package/dist/cli.js CHANGED
@@ -434,5 +434,4 @@ main().catch((error) => {
434
434
  });
435
435
 
436
436
  //#endregion
437
- export { };
438
- //# sourceMappingURL=cli.js.map
437
+ export { };
@@ -1484,5 +1484,4 @@ Object.defineProperty(exports, 'toSnapshotDiffFromReport', {
1484
1484
  get: function () {
1485
1485
  return toSnapshotDiffFromReport;
1486
1486
  }
1487
- });
1488
- //# sourceMappingURL=generate-CHjGIFJe.cjs.map
1487
+ });
@@ -1241,5 +1241,4 @@ function normaliseEventId(id) {
1241
1241
  }
1242
1242
 
1243
1243
  //#endregion
1244
- export { countDriftEntries as A, renderJson as C, renderMarkdown as D, renderDeltaMarkdown as E, readCatalogState as F, loadSnapshot as I, diffCatalogAgainstSnapshot as M, hasDrift as N, compareDriftReports as O, extractDeclaredFieldPaths as P, REPORT_SPEC as S, renderTerminal as T, EVENTCATALOG_SNAPSHOT_DIFF_SPEC as _, STAMP_END as a, toSnapshotDiffFromDelta as b, buildStampBlock as c, evaluatePolicy as d, RENDERERS as f, registerRenderer as g, listRendererNames as h, inferJsonSchemaFromObservation as i, countDriftReport as j, countDriftDelta as k, buildStampSummary as l, getRenderer as m, buildGenerateSummary as n, STAMP_START as o, RENDERER_NAMES as p, generateCatalogFromSnapshot as r, STAMP_SUMMARY_SPEC as s, GENERATE_SUMMARY_SPEC as t, stampCatalog as u, renderEventCatalogSnapshotDiffFromDelta as v, renderDeltaTerminal as w, toSnapshotDiffFromReport as x, renderEventCatalogSnapshotDiffFromReport as y };
1245
- //# sourceMappingURL=generate-r5KccyNS.js.map
1244
+ export { countDriftEntries as A, renderJson as C, renderMarkdown as D, renderDeltaMarkdown as E, readCatalogState as F, loadSnapshot as I, diffCatalogAgainstSnapshot as M, hasDrift as N, compareDriftReports as O, extractDeclaredFieldPaths as P, REPORT_SPEC as S, renderTerminal as T, EVENTCATALOG_SNAPSHOT_DIFF_SPEC as _, STAMP_END as a, toSnapshotDiffFromDelta as b, buildStampBlock as c, evaluatePolicy as d, RENDERERS as f, registerRenderer as g, listRendererNames as h, inferJsonSchemaFromObservation as i, countDriftReport as j, countDriftDelta as k, buildStampSummary as l, getRenderer as m, buildGenerateSummary as n, STAMP_START as o, RENDERER_NAMES as p, generateCatalogFromSnapshot as r, STAMP_SUMMARY_SPEC as s, GENERATE_SUMMARY_SPEC as t, stampCatalog as u, renderEventCatalogSnapshotDiffFromDelta as v, renderDeltaTerminal as w, toSnapshotDiffFromReport as x, renderEventCatalogSnapshotDiffFromReport as y };
package/dist/index.d.cts CHANGED
@@ -415,5 +415,4 @@ declare function buildGenerateSummary(result: GenerateResult, options: {
415
415
  }): GenerateSummary;
416
416
  declare function inferJsonSchemaFromObservation(observation: EventObservation): Record<string, unknown>;
417
417
  //#endregion
418
- export { type ArchitectureSnapshot, type CatalogChannel, type CatalogEvent, type CatalogService, type CatalogState, type ChannelDrift, type DriftCounts, type DriftDelta, type DriftEntries, type DriftPolicyMode, type DriftReport, EVENTCATALOG_SNAPSHOT_DIFF_SPEC, type EventCatalogSnapshotDiff, type EventCatalogSnapshotDiffEnvelope, type EventDrift, type EventObservation, type FieldDrift, GENERATE_SUMMARY_SPEC, type GenerateOptions, type GenerateResult, type GenerateSummary, type GenerateSummaryItem, type JsonReport, type JsonReportEnvelope, type PolicyEvaluationInput, type PolicyEvaluationResult, RENDERERS, RENDERER_NAMES, REPORT_SPEC, type RelationshipChange, type Renderer, type RendererName, type ResourceChange, STAMP_END, STAMP_START, STAMP_SUMMARY_SPEC, type ServiceDrift, type StampOptions, type StampResult, type StampSkip, type StampSummary, type StampUpdate, buildGenerateSummary, buildStampBlock, buildStampSummary, compareDriftReports, countDriftDelta, countDriftEntries, countDriftReport, diffCatalogAgainstSnapshot, evaluatePolicy, extractDeclaredFieldPaths, generateCatalogFromSnapshot, getRenderer, hasDrift, inferJsonSchemaFromObservation, loadSnapshot, readCatalogState, renderDeltaMarkdown, renderDeltaTerminal, renderEventCatalogSnapshotDiffFromDelta, renderEventCatalogSnapshotDiffFromReport, renderJson, renderMarkdown, renderTerminal, stampCatalog, toSnapshotDiffFromDelta, toSnapshotDiffFromReport };
419
- //# sourceMappingURL=index.d.cts.map
418
+ export { type ArchitectureSnapshot, type CatalogChannel, type CatalogEvent, type CatalogService, type CatalogState, type ChannelDrift, type DriftCounts, type DriftDelta, type DriftEntries, type DriftPolicyMode, type DriftReport, EVENTCATALOG_SNAPSHOT_DIFF_SPEC, type EventCatalogSnapshotDiff, type EventCatalogSnapshotDiffEnvelope, type EventDrift, type EventObservation, type FieldDrift, GENERATE_SUMMARY_SPEC, type GenerateOptions, type GenerateResult, type GenerateSummary, type GenerateSummaryItem, type JsonReport, type JsonReportEnvelope, type PolicyEvaluationInput, type PolicyEvaluationResult, RENDERERS, RENDERER_NAMES, REPORT_SPEC, type RelationshipChange, type Renderer, type RendererName, type ResourceChange, STAMP_END, STAMP_START, STAMP_SUMMARY_SPEC, type ServiceDrift, type StampOptions, type StampResult, type StampSkip, type StampSummary, type StampUpdate, buildGenerateSummary, buildStampBlock, buildStampSummary, compareDriftReports, countDriftDelta, countDriftEntries, countDriftReport, diffCatalogAgainstSnapshot, evaluatePolicy, extractDeclaredFieldPaths, generateCatalogFromSnapshot, getRenderer, hasDrift, inferJsonSchemaFromObservation, loadSnapshot, readCatalogState, renderDeltaMarkdown, renderDeltaTerminal, renderEventCatalogSnapshotDiffFromDelta, renderEventCatalogSnapshotDiffFromReport, renderJson, renderMarkdown, renderTerminal, stampCatalog, toSnapshotDiffFromDelta, toSnapshotDiffFromReport };
package/dist/index.d.ts CHANGED
@@ -415,5 +415,4 @@ declare function buildGenerateSummary(result: GenerateResult, options: {
415
415
  }): GenerateSummary;
416
416
  declare function inferJsonSchemaFromObservation(observation: EventObservation): Record<string, unknown>;
417
417
  //#endregion
418
- export { type ArchitectureSnapshot, type CatalogChannel, type CatalogEvent, type CatalogService, type CatalogState, type ChannelDrift, type DriftCounts, type DriftDelta, type DriftEntries, type DriftPolicyMode, type DriftReport, EVENTCATALOG_SNAPSHOT_DIFF_SPEC, type EventCatalogSnapshotDiff, type EventCatalogSnapshotDiffEnvelope, type EventDrift, type EventObservation, type FieldDrift, GENERATE_SUMMARY_SPEC, type GenerateOptions, type GenerateResult, type GenerateSummary, type GenerateSummaryItem, type JsonReport, type JsonReportEnvelope, type PolicyEvaluationInput, type PolicyEvaluationResult, RENDERERS, RENDERER_NAMES, REPORT_SPEC, type RelationshipChange, type Renderer, type RendererName, type ResourceChange, STAMP_END, STAMP_START, STAMP_SUMMARY_SPEC, type ServiceDrift, type StampOptions, type StampResult, type StampSkip, type StampSummary, type StampUpdate, buildGenerateSummary, buildStampBlock, buildStampSummary, compareDriftReports, countDriftDelta, countDriftEntries, countDriftReport, diffCatalogAgainstSnapshot, evaluatePolicy, extractDeclaredFieldPaths, generateCatalogFromSnapshot, getRenderer, hasDrift, inferJsonSchemaFromObservation, loadSnapshot, readCatalogState, renderDeltaMarkdown, renderDeltaTerminal, renderEventCatalogSnapshotDiffFromDelta, renderEventCatalogSnapshotDiffFromReport, renderJson, renderMarkdown, renderTerminal, stampCatalog, toSnapshotDiffFromDelta, toSnapshotDiffFromReport };
419
- //# sourceMappingURL=index.d.ts.map
418
+ export { type ArchitectureSnapshot, type CatalogChannel, type CatalogEvent, type CatalogService, type CatalogState, type ChannelDrift, type DriftCounts, type DriftDelta, type DriftEntries, type DriftPolicyMode, type DriftReport, EVENTCATALOG_SNAPSHOT_DIFF_SPEC, type EventCatalogSnapshotDiff, type EventCatalogSnapshotDiffEnvelope, type EventDrift, type EventObservation, type FieldDrift, GENERATE_SUMMARY_SPEC, type GenerateOptions, type GenerateResult, type GenerateSummary, type GenerateSummaryItem, type JsonReport, type JsonReportEnvelope, type PolicyEvaluationInput, type PolicyEvaluationResult, RENDERERS, RENDERER_NAMES, REPORT_SPEC, type RelationshipChange, type Renderer, type RendererName, type ResourceChange, STAMP_END, STAMP_START, STAMP_SUMMARY_SPEC, type ServiceDrift, type StampOptions, type StampResult, type StampSkip, type StampSummary, type StampUpdate, buildGenerateSummary, buildStampBlock, buildStampSummary, compareDriftReports, countDriftDelta, countDriftEntries, countDriftReport, diffCatalogAgainstSnapshot, evaluatePolicy, extractDeclaredFieldPaths, generateCatalogFromSnapshot, getRenderer, hasDrift, inferJsonSchemaFromObservation, loadSnapshot, readCatalogState, renderDeltaMarkdown, renderDeltaTerminal, renderEventCatalogSnapshotDiffFromDelta, renderEventCatalogSnapshotDiffFromReport, renderJson, renderMarkdown, renderTerminal, stampCatalog, toSnapshotDiffFromDelta, toSnapshotDiffFromReport };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "autotel-eventcatalog",
3
- "version": "15.0.0",
3
+ "version": "16.0.0",
4
4
  "description": "Diff your autotel architecture snapshot against an EventCatalog and report drift. Same model as Pact, for event architectures.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -50,15 +50,15 @@
50
50
  "autotel-subscribers": "*"
51
51
  },
52
52
  "devDependencies": {
53
- "@types/node": "^26.1.1",
53
+ "@types/node": "^26.1.2",
54
54
  "rimraf": "^6.1.3",
55
- "tsdown": "^0.22.12",
55
+ "tsdown": "^0.22.14",
56
56
  "typescript": "^6.0.3",
57
57
  "vitest": "^4.1.10",
58
- "autotel-subscribers": "45.0.0"
58
+ "autotel-subscribers": "46.0.0"
59
59
  },
60
60
  "dependencies": {
61
- "@eventcatalog/sdk": "^2.26.2"
61
+ "@eventcatalog/sdk": "^2.26.3"
62
62
  },
63
63
  "scripts": {
64
64
  "build": "tsdown",
package/dist/cli.cjs.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli.cjs","names":["getRenderer","listRendererNames","loadSnapshot","readCatalogState","diffCatalogAgainstSnapshot","compareDriftReports","evaluatePolicy","countDriftEntries","countDriftReport","stampCatalog","buildStampSummary","generateCatalogFromSnapshot","buildGenerateSummary"],"sources":["../src/cli.ts"],"sourcesContent":["import { writeFile, mkdir } from 'node:fs/promises';\nimport { dirname, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { loadSnapshot } from './snapshot';\nimport { readCatalogState } from './catalog';\nimport { diffCatalogAgainstSnapshot, countDriftReport } from './diff';\nimport { compareDriftReports, countDriftEntries } from './diff-vs-base';\nimport {\n getRenderer,\n listRendererNames,\n registerRenderer,\n} from './renderers/index';\nimport type { Renderer } from './renderers/types';\nimport { evaluatePolicy, type DriftPolicyMode } from './policy';\nimport { stampCatalog, buildStampSummary } from './stamp';\nimport { generateCatalogFromSnapshot, buildGenerateSummary } from './generate';\n\n/** Built-in renderer names. Kept as a string so the type allows future\n * renderers (sarif, slack, ...) without churning the CLI argument type. */\ntype OutputFormat = string;\n\ntype DriftArgs = {\n command: 'drift';\n snapshot: string;\n baseSnapshot?: string;\n catalog: string;\n output?: string;\n summaryOutput?: string;\n failOnDrift: boolean;\n /** undefined ⇒ derived at use site: new-only when baseSnapshot present, else all. */\n policy: DriftPolicyMode | undefined;\n format: OutputFormat;\n};\n\ntype StampArgs = {\n command: 'stamp';\n snapshot: string;\n catalog: string;\n dryRun: boolean;\n format: 'text' | 'json';\n summaryOutput?: string;\n};\n\ntype GenerateArgs = {\n command: 'generate';\n snapshot: string;\n catalog: string;\n dryRun: boolean;\n edgesOnly: boolean;\n version: string;\n format: 'text' | 'json';\n summaryOutput?: string;\n};\n\nfunction parsePlainFormat(value: string | undefined): 'text' | 'json' {\n if (value === 'json' || value === 'text') return value;\n process.stderr.write(\n `Invalid --format value: ${value}. Expected 'text' or 'json'.\\n`,\n );\n process.exit(2);\n}\n\n/**\n * Read the next argv as the value for `flag`. Rejects \"next argv is itself a\n * flag\" (`--snapshot --catalog ./cat` would otherwise silently set\n * snapshot to `--catalog`).\n */\nfunction requireValue(rest: string[], index: number, flag: string): string {\n const value = rest[index];\n if (value === undefined || value.startsWith('--')) {\n process.stderr.write(`Missing value for ${flag}\\n`);\n process.exit(2);\n }\n return value;\n}\n\nfunction isRenderer(value: unknown): value is Renderer {\n if (!value || typeof value !== 'object') return false;\n const r = value as Renderer;\n return (\n typeof r.name === 'string' &&\n typeof r.description === 'string' &&\n typeof r.renderReport === 'function' &&\n typeof r.renderDelta === 'function'\n );\n}\n\nasync function loadRendererModule(modulePath: string): Promise<void> {\n const resolved = resolve(process.cwd(), modulePath);\n let mod: Record<string, unknown>;\n try {\n mod = (await import(pathToFileURL(resolved).href)) as Record<\n string,\n unknown\n >;\n } catch (error) {\n process.stderr.write(\n `Failed to load renderer module ${modulePath}: ${(error as Error).message}\\n`,\n );\n process.exit(2);\n }\n\n // Accept the renderer as either the default export or under `renderer`.\n // The latter is friendlier for CommonJS / non-default-aware setups.\n const candidate = mod.default ?? mod.renderer;\n if (!isRenderer(candidate)) {\n process.stderr.write(\n `Module ${modulePath} does not export a Renderer (expected \\`default\\` or \\`renderer\\` matching { name, description, renderReport, renderDelta }).\\n`,\n );\n process.exit(2);\n }\n\n try {\n registerRenderer(candidate);\n } catch (error) {\n process.stderr.write(`${(error as Error).message}\\n`);\n process.exit(2);\n }\n}\n\n/**\n * Strip `--register-renderer <path>` (and `=path`) from argv, load each\n * module, and return the remaining argv for subcommand parsing.\n */\nasync function processRegisterRendererFlags(argv: string[]): Promise<string[]> {\n const remaining: string[] = [];\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i]!;\n if (arg === '--register-renderer') {\n const modulePath = requireValue(argv, ++i, '--register-renderer');\n await loadRendererModule(modulePath);\n continue;\n }\n if (arg.startsWith('--register-renderer=')) {\n const modulePath = arg.slice('--register-renderer='.length);\n if (!modulePath) {\n process.stderr.write('Missing value for --register-renderer\\n');\n process.exit(2);\n }\n await loadRendererModule(modulePath);\n continue;\n }\n remaining.push(arg);\n }\n return remaining;\n}\n\ntype Args = DriftArgs | StampArgs | GenerateArgs;\n\nfunction parseArgs(argv: string[]): Args {\n const [command, ...rest] = argv;\n if (command !== 'drift' && command !== 'stamp' && command !== 'generate') {\n usage();\n process.exit(2);\n }\n\n if (command === 'generate') {\n return parseGenerateArgs(rest);\n }\n\n if (command === 'stamp') {\n return parseStampArgs(rest);\n }\n\n return parseDriftArgs(rest);\n}\n\nfunction parseDriftArgs(rest: string[]): DriftArgs {\n let snapshot: string | undefined;\n let baseSnapshot: string | undefined;\n let catalog: string | undefined;\n let output: string | undefined;\n let summaryOutput: string | undefined;\n let failOnDrift = false;\n let policy: DriftPolicyMode | undefined;\n let format: OutputFormat = 'markdown';\n\n for (let i = 0; i < rest.length; i++) {\n const arg = rest[i];\n switch (arg) {\n case '--snapshot': {\n snapshot = requireValue(rest, ++i, '--snapshot');\n break;\n }\n case '--base-snapshot': {\n baseSnapshot = requireValue(rest, ++i, '--base-snapshot');\n break;\n }\n case '--catalog': {\n catalog = requireValue(rest, ++i, '--catalog');\n break;\n }\n case '--output': {\n output = requireValue(rest, ++i, '--output');\n break;\n }\n case '--summary-output': {\n summaryOutput = requireValue(rest, ++i, '--summary-output');\n break;\n }\n case '--fail-on-drift': {\n failOnDrift = true;\n break;\n }\n case '--policy': {\n const value = requireValue(rest, ++i, '--policy');\n if (value !== 'all' && value !== 'new-only') {\n process.stderr.write(\n `Invalid --policy value: ${value}. Use 'all' or 'new-only'.\\n`,\n );\n process.exit(2);\n }\n policy = value;\n break;\n }\n case '--format': {\n const value = requireValue(rest, ++i, '--format');\n if (!getRenderer(value)) {\n process.stderr.write(\n `Invalid --format value: ${value}. Available renderers: ${listRendererNames().join(', ')}.\\n`,\n );\n process.exit(2);\n }\n format = value;\n break;\n }\n case '-h':\n case '--help': {\n usage();\n process.exit(0);\n break;\n }\n default: {\n process.stderr.write(`Unknown argument: ${arg}\\n`);\n usage();\n process.exit(2);\n }\n }\n }\n\n if (!snapshot || !catalog) {\n process.stderr.write('Both --snapshot and --catalog are required.\\n');\n usage();\n process.exit(2);\n }\n\n if (policy === 'new-only' && !baseSnapshot) {\n process.stderr.write('--policy new-only requires --base-snapshot.\\n');\n process.exit(2);\n }\n\n // Note: the *effective* policy is derived at use site (see runDrift).\n // When the user omits --policy, the choice is \"new-only when\n // --base-snapshot is present, else all\"; explicit at the call site,\n // never via a silent flag rewrite here.\n\n return {\n command: 'drift',\n snapshot: resolve(snapshot),\n baseSnapshot: baseSnapshot ? resolve(baseSnapshot) : undefined,\n catalog: resolve(catalog),\n output: output ? resolve(output) : undefined,\n summaryOutput: summaryOutput ? resolve(summaryOutput) : undefined,\n failOnDrift,\n policy,\n format,\n };\n}\n\nfunction parseStampArgs(rest: string[]): StampArgs {\n let snapshot: string | undefined;\n let catalog: string | undefined;\n let dryRun = false;\n let format: 'text' | 'json' = 'text';\n let summaryOutput: string | undefined;\n\n for (let i = 0; i < rest.length; i++) {\n const arg = rest[i];\n switch (arg) {\n case '--snapshot': {\n snapshot = requireValue(rest, ++i, '--snapshot');\n break;\n }\n case '--catalog': {\n catalog = requireValue(rest, ++i, '--catalog');\n break;\n }\n case '--dry-run': {\n dryRun = true;\n break;\n }\n case '--format': {\n format = parsePlainFormat(requireValue(rest, ++i, '--format'));\n break;\n }\n case '--summary-output': {\n summaryOutput = requireValue(rest, ++i, '--summary-output');\n break;\n }\n case '-h':\n case '--help': {\n usage();\n process.exit(0);\n break;\n }\n default: {\n process.stderr.write(`Unknown argument: ${arg}\\n`);\n usage();\n process.exit(2);\n }\n }\n }\n\n if (!snapshot || !catalog) {\n process.stderr.write(\n 'Both --snapshot and --catalog are required for stamp.\\n',\n );\n usage();\n process.exit(2);\n }\n\n return {\n command: 'stamp',\n snapshot: resolve(snapshot),\n catalog: resolve(catalog),\n dryRun,\n format,\n summaryOutput: summaryOutput ? resolve(summaryOutput) : undefined,\n };\n}\n\nfunction parseGenerateArgs(rest: string[]): GenerateArgs {\n let snapshot: string | undefined;\n let catalog: string | undefined;\n let dryRun = false;\n let edgesOnly = false;\n let version = '1.0.0';\n let format: 'text' | 'json' = 'text';\n let summaryOutput: string | undefined;\n\n for (let i = 0; i < rest.length; i++) {\n const arg = rest[i];\n switch (arg) {\n case '--snapshot': {\n snapshot = requireValue(rest, ++i, '--snapshot');\n break;\n }\n case '--catalog': {\n catalog = requireValue(rest, ++i, '--catalog');\n break;\n }\n case '--dry-run': {\n dryRun = true;\n break;\n }\n case '--edges-only': {\n edgesOnly = true;\n break;\n }\n case '--version': {\n version = requireValue(rest, ++i, '--version');\n break;\n }\n case '--format': {\n format = parsePlainFormat(requireValue(rest, ++i, '--format'));\n break;\n }\n case '--summary-output': {\n summaryOutput = requireValue(rest, ++i, '--summary-output');\n break;\n }\n case '-h':\n case '--help': {\n usage();\n process.exit(0);\n break;\n }\n default: {\n process.stderr.write(`Unknown argument: ${arg}\\n`);\n usage();\n process.exit(2);\n }\n }\n }\n\n if (!snapshot || !catalog) {\n process.stderr.write(\n 'Both --snapshot and --catalog are required for generate.\\n',\n );\n usage();\n process.exit(2);\n }\n\n return {\n command: 'generate',\n snapshot: resolve(snapshot),\n catalog: resolve(catalog),\n dryRun,\n edgesOnly,\n version,\n format,\n summaryOutput: summaryOutput ? resolve(summaryOutput) : undefined,\n };\n}\n\nfunction usage(): void {\n process.stderr.write(\n [\n 'Usage:',\n ' autotel-eventcatalog drift --snapshot <path> --catalog <path> [options]',\n ' autotel-eventcatalog stamp --snapshot <path> --catalog <path> [--dry-run]',\n ' autotel-eventcatalog generate --snapshot <path> --catalog <path> [options]',\n '',\n 'Global options (any command):',\n ' --register-renderer <module> Dynamically import a Renderer (default export',\n ' or named `renderer`) and register it before the',\n \" command runs. The renderer's `name` then works\",\n ' with --format. May be passed multiple times.',\n '',\n 'drift options:',\n ' --snapshot <path> Path to the autotel architecture snapshot JSON',\n ' --base-snapshot <path> Path to a baseline snapshot (typically PR base branch).',\n ' --catalog <path> Path to the EventCatalog root',\n ' --output <path> Write the report to this file',\n ' --summary-output <path> Write a machine-readable drift summary JSON file',\n \" --policy <mode> Drift fail policy: 'all' | 'new-only'\",\n ` --format <kind> Output format: ${listRendererNames().join(' | ')}`,\n ' --fail-on-drift Exit non-zero when policy marks drift as failing',\n '',\n 'stamp options:',\n ' --snapshot <path> Architecture snapshot JSON',\n ' --catalog <path> EventCatalog root',\n ' --dry-run Print the update plan without writing files',\n \" --format <kind> Output format: 'text' (default) | 'json'\",\n ' --summary-output <path> Write a machine-readable stamp summary JSON file',\n '',\n 'generate options:',\n ' --snapshot <path> Architecture snapshot JSON',\n ' --catalog <path> EventCatalog root',\n ' --dry-run Print the generation plan without writing files',\n ' --edges-only Only generate producer/event/channel edges',\n ' --version <semver> Version to assign to newly generated resources (default: 1.0.0)',\n \" --format <kind> Output format: 'text' (default) | 'json'\",\n ' --summary-output <path> Write a machine-readable generate summary JSON file',\n '',\n ' -h, --help Show this help',\n '',\n ].join('\\n'),\n );\n}\n\nasync function runDrift(args: DriftArgs): Promise<void> {\n const headSnapshot = await loadSnapshot(args.snapshot);\n const catalog = await readCatalogState(args.catalog);\n const headReport = diffCatalogAgainstSnapshot(headSnapshot, catalog);\n\n const delta = args.baseSnapshot\n ? compareDriftReports(\n diffCatalogAgainstSnapshot(\n await loadSnapshot(args.baseSnapshot),\n catalog,\n ),\n headReport,\n )\n : undefined;\n\n // Effective policy: explicit flag wins; otherwise derive from whether a\n // baseline snapshot is present.\n const effectivePolicy: DriftPolicyMode =\n args.policy ?? (delta ? 'new-only' : 'all');\n\n const policyResult =\n effectivePolicy === 'new-only' && delta\n ? evaluatePolicy({ mode: 'new-only', delta })\n : evaluatePolicy({ mode: 'all', report: headReport });\n\n // Dispatch through the renderer registry. Every renderer implements both\n // shapes; the right one is picked based on the effective policy.\n const renderer = getRenderer(args.format);\n if (!renderer) {\n // Defensive. parseDriftArgs already validates this, but make the\n // runtime failure mode unambiguous.\n process.stderr.write(`Unknown renderer: ${args.format}\\n`);\n process.exit(2);\n }\n const output =\n effectivePolicy === 'new-only' && delta\n ? renderer.renderDelta(delta)\n : renderer.renderReport(headReport);\n\n process.stdout.write(output);\n if (!output.endsWith('\\n')) process.stdout.write('\\n');\n\n if (args.output) {\n await mkdir(dirname(args.output), { recursive: true });\n await writeFile(args.output, output, 'utf8');\n process.stderr.write(`\\nWrote drift report: ${args.output}\\n`);\n }\n\n const summary = buildSummary(\n effectivePolicy,\n headReport,\n delta,\n policyResult,\n );\n if (args.summaryOutput) {\n await mkdir(dirname(args.summaryOutput), { recursive: true });\n await writeFile(\n args.summaryOutput,\n JSON.stringify(summary, null, 2),\n 'utf8',\n );\n process.stderr.write(`Wrote drift summary: ${args.summaryOutput}\\n`);\n }\n\n // Always surface the policy outcome to stderr so CI logs explain *why*\n // the job ended the way it did. A \"No drift detected\" log line is as\n // useful as a \"Drift detected\" line when reading a CI run after the fact.\n process.stderr.write(`\\n${policyResult.reason}\\n`);\n\n if (args.failOnDrift && policyResult.shouldFail) {\n process.exit(1);\n }\n}\n\nconst DRIFT_SUMMARY_SPEC = 'autotel-eventcatalog-drift-summary/v0.2.0' as const;\n\ntype DriftSummary = {\n spec: typeof DRIFT_SUMMARY_SPEC;\n mode: DriftPolicyMode;\n shouldFail: boolean;\n reason: string;\n counts: ReturnType<typeof countDriftReport>;\n};\n\nfunction buildSummary(\n mode: DriftPolicyMode,\n headReport: ReturnType<typeof diffCatalogAgainstSnapshot>,\n delta: ReturnType<typeof compareDriftReports> | undefined,\n policyResult: ReturnType<typeof evaluatePolicy>,\n): DriftSummary {\n const counts =\n mode === 'new-only' && delta\n ? countDriftEntries(delta.introduced)\n : countDriftReport(headReport);\n return {\n spec: DRIFT_SUMMARY_SPEC,\n mode,\n shouldFail: policyResult.shouldFail,\n reason: policyResult.reason,\n counts,\n };\n}\n\nasync function runStamp(args: StampArgs): Promise<void> {\n const snapshot = await loadSnapshot(args.snapshot);\n const result = await stampCatalog({\n snapshot,\n catalogPath: args.catalog,\n dryRun: args.dryRun,\n });\n\n const summary = buildStampSummary(result, args.dryRun);\n\n if (args.format === 'json') {\n process.stdout.write(\n JSON.stringify(\n {\n summary,\n updates: result.updates,\n skips: result.skips,\n },\n null,\n 2,\n ) + '\\n',\n );\n } else {\n for (const upd of result.updates) {\n const verb = args.dryRun\n ? `would ${upd.action}`\n : upd.changed\n ? upd.action\n : 'unchanged';\n process.stdout.write(`${verb} ${upd.catalogId} -> ${upd.filePath}\\n`);\n }\n for (const skip of result.skips) {\n process.stdout.write(`skip ${skip.snapshotName} (${skip.reason})\\n`);\n }\n\n process.stderr.write(\n `\\n${summary.changedFiles} changed, ${summary.replaces} replaces, ${summary.inserts} inserts, ${summary.skipped} skipped${\n args.dryRun ? ' (dry run)' : ''\n }\\n`,\n );\n }\n\n if (args.summaryOutput) {\n await mkdir(dirname(args.summaryOutput), { recursive: true });\n await writeFile(\n args.summaryOutput,\n JSON.stringify(summary, null, 2),\n 'utf8',\n );\n process.stderr.write(`Wrote stamp summary: ${args.summaryOutput}\\n`);\n }\n}\n\nasync function runGenerate(args: GenerateArgs): Promise<void> {\n const snapshot = await loadSnapshot(args.snapshot);\n const result = await generateCatalogFromSnapshot({\n snapshot,\n catalogPath: args.catalog,\n dryRun: args.dryRun,\n edgesOnly: args.edgesOnly,\n version: args.version,\n });\n\n const summary = buildGenerateSummary(result, {\n dryRun: args.dryRun,\n edgesOnly: args.edgesOnly,\n });\n\n if (args.format === 'json') {\n process.stdout.write(\n JSON.stringify({ summary, operations: result.operations }, null, 2) +\n '\\n',\n );\n } else {\n for (const op of result.operations) {\n const suffix = op.schemaSource ? ` (schema: ${op.schemaSource})` : '';\n process.stdout.write(`${op.action} ${op.kind} ${op.id}${suffix}\\n`);\n }\n if (result.operations.length === 0) {\n process.stdout.write('No generation operations needed.\\n');\n }\n }\n\n if (args.summaryOutput) {\n await mkdir(dirname(args.summaryOutput), { recursive: true });\n await writeFile(\n args.summaryOutput,\n JSON.stringify(summary, null, 2),\n 'utf8',\n );\n process.stderr.write(`Wrote generate summary: ${args.summaryOutput}\\n`);\n }\n}\n\nasync function main(): Promise<void> {\n // Process --register-renderer flags before parsing the subcommand so the\n // format validator sees the freshly-registered name.\n const argv = await processRegisterRendererFlags(process.argv.slice(2));\n const args = parseArgs(argv);\n if (args.command === 'stamp') {\n await runStamp(args);\n return;\n }\n if (args.command === 'generate') {\n await runGenerate(args);\n return;\n }\n await runDrift(args);\n}\n\nmain().catch((error) => {\n process.stderr.write(`autotel-eventcatalog: ${(error as Error).message}\\n`);\n process.exit(1);\n});\n"],"mappings":"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"}
package/dist/cli.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli.js","names":[],"sources":["../src/cli.ts"],"sourcesContent":["import { writeFile, mkdir } from 'node:fs/promises';\nimport { dirname, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { loadSnapshot } from './snapshot';\nimport { readCatalogState } from './catalog';\nimport { diffCatalogAgainstSnapshot, countDriftReport } from './diff';\nimport { compareDriftReports, countDriftEntries } from './diff-vs-base';\nimport {\n getRenderer,\n listRendererNames,\n registerRenderer,\n} from './renderers/index';\nimport type { Renderer } from './renderers/types';\nimport { evaluatePolicy, type DriftPolicyMode } from './policy';\nimport { stampCatalog, buildStampSummary } from './stamp';\nimport { generateCatalogFromSnapshot, buildGenerateSummary } from './generate';\n\n/** Built-in renderer names. Kept as a string so the type allows future\n * renderers (sarif, slack, ...) without churning the CLI argument type. */\ntype OutputFormat = string;\n\ntype DriftArgs = {\n command: 'drift';\n snapshot: string;\n baseSnapshot?: string;\n catalog: string;\n output?: string;\n summaryOutput?: string;\n failOnDrift: boolean;\n /** undefined ⇒ derived at use site: new-only when baseSnapshot present, else all. */\n policy: DriftPolicyMode | undefined;\n format: OutputFormat;\n};\n\ntype StampArgs = {\n command: 'stamp';\n snapshot: string;\n catalog: string;\n dryRun: boolean;\n format: 'text' | 'json';\n summaryOutput?: string;\n};\n\ntype GenerateArgs = {\n command: 'generate';\n snapshot: string;\n catalog: string;\n dryRun: boolean;\n edgesOnly: boolean;\n version: string;\n format: 'text' | 'json';\n summaryOutput?: string;\n};\n\nfunction parsePlainFormat(value: string | undefined): 'text' | 'json' {\n if (value === 'json' || value === 'text') return value;\n process.stderr.write(\n `Invalid --format value: ${value}. Expected 'text' or 'json'.\\n`,\n );\n process.exit(2);\n}\n\n/**\n * Read the next argv as the value for `flag`. Rejects \"next argv is itself a\n * flag\" (`--snapshot --catalog ./cat` would otherwise silently set\n * snapshot to `--catalog`).\n */\nfunction requireValue(rest: string[], index: number, flag: string): string {\n const value = rest[index];\n if (value === undefined || value.startsWith('--')) {\n process.stderr.write(`Missing value for ${flag}\\n`);\n process.exit(2);\n }\n return value;\n}\n\nfunction isRenderer(value: unknown): value is Renderer {\n if (!value || typeof value !== 'object') return false;\n const r = value as Renderer;\n return (\n typeof r.name === 'string' &&\n typeof r.description === 'string' &&\n typeof r.renderReport === 'function' &&\n typeof r.renderDelta === 'function'\n );\n}\n\nasync function loadRendererModule(modulePath: string): Promise<void> {\n const resolved = resolve(process.cwd(), modulePath);\n let mod: Record<string, unknown>;\n try {\n mod = (await import(pathToFileURL(resolved).href)) as Record<\n string,\n unknown\n >;\n } catch (error) {\n process.stderr.write(\n `Failed to load renderer module ${modulePath}: ${(error as Error).message}\\n`,\n );\n process.exit(2);\n }\n\n // Accept the renderer as either the default export or under `renderer`.\n // The latter is friendlier for CommonJS / non-default-aware setups.\n const candidate = mod.default ?? mod.renderer;\n if (!isRenderer(candidate)) {\n process.stderr.write(\n `Module ${modulePath} does not export a Renderer (expected \\`default\\` or \\`renderer\\` matching { name, description, renderReport, renderDelta }).\\n`,\n );\n process.exit(2);\n }\n\n try {\n registerRenderer(candidate);\n } catch (error) {\n process.stderr.write(`${(error as Error).message}\\n`);\n process.exit(2);\n }\n}\n\n/**\n * Strip `--register-renderer <path>` (and `=path`) from argv, load each\n * module, and return the remaining argv for subcommand parsing.\n */\nasync function processRegisterRendererFlags(argv: string[]): Promise<string[]> {\n const remaining: string[] = [];\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i]!;\n if (arg === '--register-renderer') {\n const modulePath = requireValue(argv, ++i, '--register-renderer');\n await loadRendererModule(modulePath);\n continue;\n }\n if (arg.startsWith('--register-renderer=')) {\n const modulePath = arg.slice('--register-renderer='.length);\n if (!modulePath) {\n process.stderr.write('Missing value for --register-renderer\\n');\n process.exit(2);\n }\n await loadRendererModule(modulePath);\n continue;\n }\n remaining.push(arg);\n }\n return remaining;\n}\n\ntype Args = DriftArgs | StampArgs | GenerateArgs;\n\nfunction parseArgs(argv: string[]): Args {\n const [command, ...rest] = argv;\n if (command !== 'drift' && command !== 'stamp' && command !== 'generate') {\n usage();\n process.exit(2);\n }\n\n if (command === 'generate') {\n return parseGenerateArgs(rest);\n }\n\n if (command === 'stamp') {\n return parseStampArgs(rest);\n }\n\n return parseDriftArgs(rest);\n}\n\nfunction parseDriftArgs(rest: string[]): DriftArgs {\n let snapshot: string | undefined;\n let baseSnapshot: string | undefined;\n let catalog: string | undefined;\n let output: string | undefined;\n let summaryOutput: string | undefined;\n let failOnDrift = false;\n let policy: DriftPolicyMode | undefined;\n let format: OutputFormat = 'markdown';\n\n for (let i = 0; i < rest.length; i++) {\n const arg = rest[i];\n switch (arg) {\n case '--snapshot': {\n snapshot = requireValue(rest, ++i, '--snapshot');\n break;\n }\n case '--base-snapshot': {\n baseSnapshot = requireValue(rest, ++i, '--base-snapshot');\n break;\n }\n case '--catalog': {\n catalog = requireValue(rest, ++i, '--catalog');\n break;\n }\n case '--output': {\n output = requireValue(rest, ++i, '--output');\n break;\n }\n case '--summary-output': {\n summaryOutput = requireValue(rest, ++i, '--summary-output');\n break;\n }\n case '--fail-on-drift': {\n failOnDrift = true;\n break;\n }\n case '--policy': {\n const value = requireValue(rest, ++i, '--policy');\n if (value !== 'all' && value !== 'new-only') {\n process.stderr.write(\n `Invalid --policy value: ${value}. Use 'all' or 'new-only'.\\n`,\n );\n process.exit(2);\n }\n policy = value;\n break;\n }\n case '--format': {\n const value = requireValue(rest, ++i, '--format');\n if (!getRenderer(value)) {\n process.stderr.write(\n `Invalid --format value: ${value}. Available renderers: ${listRendererNames().join(', ')}.\\n`,\n );\n process.exit(2);\n }\n format = value;\n break;\n }\n case '-h':\n case '--help': {\n usage();\n process.exit(0);\n break;\n }\n default: {\n process.stderr.write(`Unknown argument: ${arg}\\n`);\n usage();\n process.exit(2);\n }\n }\n }\n\n if (!snapshot || !catalog) {\n process.stderr.write('Both --snapshot and --catalog are required.\\n');\n usage();\n process.exit(2);\n }\n\n if (policy === 'new-only' && !baseSnapshot) {\n process.stderr.write('--policy new-only requires --base-snapshot.\\n');\n process.exit(2);\n }\n\n // Note: the *effective* policy is derived at use site (see runDrift).\n // When the user omits --policy, the choice is \"new-only when\n // --base-snapshot is present, else all\"; explicit at the call site,\n // never via a silent flag rewrite here.\n\n return {\n command: 'drift',\n snapshot: resolve(snapshot),\n baseSnapshot: baseSnapshot ? resolve(baseSnapshot) : undefined,\n catalog: resolve(catalog),\n output: output ? resolve(output) : undefined,\n summaryOutput: summaryOutput ? resolve(summaryOutput) : undefined,\n failOnDrift,\n policy,\n format,\n };\n}\n\nfunction parseStampArgs(rest: string[]): StampArgs {\n let snapshot: string | undefined;\n let catalog: string | undefined;\n let dryRun = false;\n let format: 'text' | 'json' = 'text';\n let summaryOutput: string | undefined;\n\n for (let i = 0; i < rest.length; i++) {\n const arg = rest[i];\n switch (arg) {\n case '--snapshot': {\n snapshot = requireValue(rest, ++i, '--snapshot');\n break;\n }\n case '--catalog': {\n catalog = requireValue(rest, ++i, '--catalog');\n break;\n }\n case '--dry-run': {\n dryRun = true;\n break;\n }\n case '--format': {\n format = parsePlainFormat(requireValue(rest, ++i, '--format'));\n break;\n }\n case '--summary-output': {\n summaryOutput = requireValue(rest, ++i, '--summary-output');\n break;\n }\n case '-h':\n case '--help': {\n usage();\n process.exit(0);\n break;\n }\n default: {\n process.stderr.write(`Unknown argument: ${arg}\\n`);\n usage();\n process.exit(2);\n }\n }\n }\n\n if (!snapshot || !catalog) {\n process.stderr.write(\n 'Both --snapshot and --catalog are required for stamp.\\n',\n );\n usage();\n process.exit(2);\n }\n\n return {\n command: 'stamp',\n snapshot: resolve(snapshot),\n catalog: resolve(catalog),\n dryRun,\n format,\n summaryOutput: summaryOutput ? resolve(summaryOutput) : undefined,\n };\n}\n\nfunction parseGenerateArgs(rest: string[]): GenerateArgs {\n let snapshot: string | undefined;\n let catalog: string | undefined;\n let dryRun = false;\n let edgesOnly = false;\n let version = '1.0.0';\n let format: 'text' | 'json' = 'text';\n let summaryOutput: string | undefined;\n\n for (let i = 0; i < rest.length; i++) {\n const arg = rest[i];\n switch (arg) {\n case '--snapshot': {\n snapshot = requireValue(rest, ++i, '--snapshot');\n break;\n }\n case '--catalog': {\n catalog = requireValue(rest, ++i, '--catalog');\n break;\n }\n case '--dry-run': {\n dryRun = true;\n break;\n }\n case '--edges-only': {\n edgesOnly = true;\n break;\n }\n case '--version': {\n version = requireValue(rest, ++i, '--version');\n break;\n }\n case '--format': {\n format = parsePlainFormat(requireValue(rest, ++i, '--format'));\n break;\n }\n case '--summary-output': {\n summaryOutput = requireValue(rest, ++i, '--summary-output');\n break;\n }\n case '-h':\n case '--help': {\n usage();\n process.exit(0);\n break;\n }\n default: {\n process.stderr.write(`Unknown argument: ${arg}\\n`);\n usage();\n process.exit(2);\n }\n }\n }\n\n if (!snapshot || !catalog) {\n process.stderr.write(\n 'Both --snapshot and --catalog are required for generate.\\n',\n );\n usage();\n process.exit(2);\n }\n\n return {\n command: 'generate',\n snapshot: resolve(snapshot),\n catalog: resolve(catalog),\n dryRun,\n edgesOnly,\n version,\n format,\n summaryOutput: summaryOutput ? resolve(summaryOutput) : undefined,\n };\n}\n\nfunction usage(): void {\n process.stderr.write(\n [\n 'Usage:',\n ' autotel-eventcatalog drift --snapshot <path> --catalog <path> [options]',\n ' autotel-eventcatalog stamp --snapshot <path> --catalog <path> [--dry-run]',\n ' autotel-eventcatalog generate --snapshot <path> --catalog <path> [options]',\n '',\n 'Global options (any command):',\n ' --register-renderer <module> Dynamically import a Renderer (default export',\n ' or named `renderer`) and register it before the',\n \" command runs. The renderer's `name` then works\",\n ' with --format. May be passed multiple times.',\n '',\n 'drift options:',\n ' --snapshot <path> Path to the autotel architecture snapshot JSON',\n ' --base-snapshot <path> Path to a baseline snapshot (typically PR base branch).',\n ' --catalog <path> Path to the EventCatalog root',\n ' --output <path> Write the report to this file',\n ' --summary-output <path> Write a machine-readable drift summary JSON file',\n \" --policy <mode> Drift fail policy: 'all' | 'new-only'\",\n ` --format <kind> Output format: ${listRendererNames().join(' | ')}`,\n ' --fail-on-drift Exit non-zero when policy marks drift as failing',\n '',\n 'stamp options:',\n ' --snapshot <path> Architecture snapshot JSON',\n ' --catalog <path> EventCatalog root',\n ' --dry-run Print the update plan without writing files',\n \" --format <kind> Output format: 'text' (default) | 'json'\",\n ' --summary-output <path> Write a machine-readable stamp summary JSON file',\n '',\n 'generate options:',\n ' --snapshot <path> Architecture snapshot JSON',\n ' --catalog <path> EventCatalog root',\n ' --dry-run Print the generation plan without writing files',\n ' --edges-only Only generate producer/event/channel edges',\n ' --version <semver> Version to assign to newly generated resources (default: 1.0.0)',\n \" --format <kind> Output format: 'text' (default) | 'json'\",\n ' --summary-output <path> Write a machine-readable generate summary JSON file',\n '',\n ' -h, --help Show this help',\n '',\n ].join('\\n'),\n );\n}\n\nasync function runDrift(args: DriftArgs): Promise<void> {\n const headSnapshot = await loadSnapshot(args.snapshot);\n const catalog = await readCatalogState(args.catalog);\n const headReport = diffCatalogAgainstSnapshot(headSnapshot, catalog);\n\n const delta = args.baseSnapshot\n ? compareDriftReports(\n diffCatalogAgainstSnapshot(\n await loadSnapshot(args.baseSnapshot),\n catalog,\n ),\n headReport,\n )\n : undefined;\n\n // Effective policy: explicit flag wins; otherwise derive from whether a\n // baseline snapshot is present.\n const effectivePolicy: DriftPolicyMode =\n args.policy ?? (delta ? 'new-only' : 'all');\n\n const policyResult =\n effectivePolicy === 'new-only' && delta\n ? evaluatePolicy({ mode: 'new-only', delta })\n : evaluatePolicy({ mode: 'all', report: headReport });\n\n // Dispatch through the renderer registry. Every renderer implements both\n // shapes; the right one is picked based on the effective policy.\n const renderer = getRenderer(args.format);\n if (!renderer) {\n // Defensive. parseDriftArgs already validates this, but make the\n // runtime failure mode unambiguous.\n process.stderr.write(`Unknown renderer: ${args.format}\\n`);\n process.exit(2);\n }\n const output =\n effectivePolicy === 'new-only' && delta\n ? renderer.renderDelta(delta)\n : renderer.renderReport(headReport);\n\n process.stdout.write(output);\n if (!output.endsWith('\\n')) process.stdout.write('\\n');\n\n if (args.output) {\n await mkdir(dirname(args.output), { recursive: true });\n await writeFile(args.output, output, 'utf8');\n process.stderr.write(`\\nWrote drift report: ${args.output}\\n`);\n }\n\n const summary = buildSummary(\n effectivePolicy,\n headReport,\n delta,\n policyResult,\n );\n if (args.summaryOutput) {\n await mkdir(dirname(args.summaryOutput), { recursive: true });\n await writeFile(\n args.summaryOutput,\n JSON.stringify(summary, null, 2),\n 'utf8',\n );\n process.stderr.write(`Wrote drift summary: ${args.summaryOutput}\\n`);\n }\n\n // Always surface the policy outcome to stderr so CI logs explain *why*\n // the job ended the way it did. A \"No drift detected\" log line is as\n // useful as a \"Drift detected\" line when reading a CI run after the fact.\n process.stderr.write(`\\n${policyResult.reason}\\n`);\n\n if (args.failOnDrift && policyResult.shouldFail) {\n process.exit(1);\n }\n}\n\nconst DRIFT_SUMMARY_SPEC = 'autotel-eventcatalog-drift-summary/v0.2.0' as const;\n\ntype DriftSummary = {\n spec: typeof DRIFT_SUMMARY_SPEC;\n mode: DriftPolicyMode;\n shouldFail: boolean;\n reason: string;\n counts: ReturnType<typeof countDriftReport>;\n};\n\nfunction buildSummary(\n mode: DriftPolicyMode,\n headReport: ReturnType<typeof diffCatalogAgainstSnapshot>,\n delta: ReturnType<typeof compareDriftReports> | undefined,\n policyResult: ReturnType<typeof evaluatePolicy>,\n): DriftSummary {\n const counts =\n mode === 'new-only' && delta\n ? countDriftEntries(delta.introduced)\n : countDriftReport(headReport);\n return {\n spec: DRIFT_SUMMARY_SPEC,\n mode,\n shouldFail: policyResult.shouldFail,\n reason: policyResult.reason,\n counts,\n };\n}\n\nasync function runStamp(args: StampArgs): Promise<void> {\n const snapshot = await loadSnapshot(args.snapshot);\n const result = await stampCatalog({\n snapshot,\n catalogPath: args.catalog,\n dryRun: args.dryRun,\n });\n\n const summary = buildStampSummary(result, args.dryRun);\n\n if (args.format === 'json') {\n process.stdout.write(\n JSON.stringify(\n {\n summary,\n updates: result.updates,\n skips: result.skips,\n },\n null,\n 2,\n ) + '\\n',\n );\n } else {\n for (const upd of result.updates) {\n const verb = args.dryRun\n ? `would ${upd.action}`\n : upd.changed\n ? upd.action\n : 'unchanged';\n process.stdout.write(`${verb} ${upd.catalogId} -> ${upd.filePath}\\n`);\n }\n for (const skip of result.skips) {\n process.stdout.write(`skip ${skip.snapshotName} (${skip.reason})\\n`);\n }\n\n process.stderr.write(\n `\\n${summary.changedFiles} changed, ${summary.replaces} replaces, ${summary.inserts} inserts, ${summary.skipped} skipped${\n args.dryRun ? ' (dry run)' : ''\n }\\n`,\n );\n }\n\n if (args.summaryOutput) {\n await mkdir(dirname(args.summaryOutput), { recursive: true });\n await writeFile(\n args.summaryOutput,\n JSON.stringify(summary, null, 2),\n 'utf8',\n );\n process.stderr.write(`Wrote stamp summary: ${args.summaryOutput}\\n`);\n }\n}\n\nasync function runGenerate(args: GenerateArgs): Promise<void> {\n const snapshot = await loadSnapshot(args.snapshot);\n const result = await generateCatalogFromSnapshot({\n snapshot,\n catalogPath: args.catalog,\n dryRun: args.dryRun,\n edgesOnly: args.edgesOnly,\n version: args.version,\n });\n\n const summary = buildGenerateSummary(result, {\n dryRun: args.dryRun,\n edgesOnly: args.edgesOnly,\n });\n\n if (args.format === 'json') {\n process.stdout.write(\n JSON.stringify({ summary, operations: result.operations }, null, 2) +\n '\\n',\n );\n } else {\n for (const op of result.operations) {\n const suffix = op.schemaSource ? ` (schema: ${op.schemaSource})` : '';\n process.stdout.write(`${op.action} ${op.kind} ${op.id}${suffix}\\n`);\n }\n if (result.operations.length === 0) {\n process.stdout.write('No generation operations needed.\\n');\n }\n }\n\n if (args.summaryOutput) {\n await mkdir(dirname(args.summaryOutput), { recursive: true });\n await writeFile(\n args.summaryOutput,\n JSON.stringify(summary, null, 2),\n 'utf8',\n );\n process.stderr.write(`Wrote generate summary: ${args.summaryOutput}\\n`);\n }\n}\n\nasync function main(): Promise<void> {\n // Process --register-renderer flags before parsing the subcommand so the\n // format validator sees the freshly-registered name.\n const argv = await processRegisterRendererFlags(process.argv.slice(2));\n const args = parseArgs(argv);\n if (args.command === 'stamp') {\n await runStamp(args);\n return;\n }\n if (args.command === 'generate') {\n await runGenerate(args);\n return;\n }\n await runDrift(args);\n}\n\nmain().catch((error) => {\n process.stderr.write(`autotel-eventcatalog: ${(error as Error).message}\\n`);\n process.exit(1);\n});\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"generate-CHjGIFJe.cjs","names":["normaliseEventId","collectChannels","normaliseEventId"],"sources":["../src/snapshot.ts","../src/catalog.ts","../src/diff.ts","../src/diff-vs-base.ts","../src/renderers/markdown.ts","../src/renderers/terminal.ts","../src/renderers/json.ts","../src/eventcatalog-snapshot-diff.ts","../src/renderers/eventcatalog-snapshot-diff.ts","../src/renderers/index.ts","../src/policy.ts","../src/stamp.ts","../src/generate.ts"],"sourcesContent":["// Re-export the snapshot types from autotel-subscribers and provide a\n// convenience loader. Keeping the types defined in one place makes the\n// contract between subscriber and generator unambiguous.\n\nimport { readFile } from 'node:fs/promises';\n\nexport type {\n ArchitectureSnapshot,\n EventObservation,\n} from 'autotel-subscribers/architecture-snapshot';\n\nimport type { ArchitectureSnapshot } from 'autotel-subscribers/architecture-snapshot';\n\nconst EXPECTED_SPEC_PREFIX = 'autotel-architecture/';\n\n/**\n * Loads and validates an autotel architecture snapshot from disk.\n *\n * Throws a descriptive error when the file is missing, contains invalid\n * JSON, or is not recognisable as an autotel snapshot, so the CLI surfaces\n * an actionable message rather than a raw `ENOENT` or `SyntaxError`.\n */\nexport async function loadSnapshot(\n path: string,\n): Promise<ArchitectureSnapshot> {\n let raw: string;\n try {\n raw = await readFile(path, 'utf8');\n } catch (err) {\n if (isNodeFsError(err) && err.code === 'ENOENT') {\n throw new Error(`Snapshot not found: ${path}`);\n }\n if (isNodeFsError(err) && err.code === 'EISDIR') {\n throw new Error(`Snapshot path is a directory, not a file: ${path}`);\n }\n throw new Error(\n `Could not read snapshot at ${path}: ${(err as Error).message}`,\n );\n }\n\n if (raw.trim().length === 0) {\n throw new Error(`Snapshot is empty: ${path}`);\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (err) {\n throw new Error(\n `Snapshot is not valid JSON: ${path} (${(err as Error).message})`,\n );\n }\n\n return validateSnapshot(parsed, path);\n}\n\n/**\n * Type guard that narrows `unknown` to `ArchitectureSnapshot` after checking\n * every required field. Replaces the previous `as ArchitectureSnapshot` cast\n * so the type story matches the runtime story: anything reaching the return\n * has been structurally verified.\n */\nfunction validateSnapshot(parsed: unknown, path: string): ArchitectureSnapshot {\n if (!isJsonObject(parsed)) {\n throw new Error(\n `Snapshot must be a JSON object: ${path} (got ${describe(parsed)})`,\n );\n }\n\n const { spec } = parsed;\n if (typeof spec !== 'string' || !spec.startsWith(EXPECTED_SPEC_PREFIX)) {\n const found =\n spec === undefined ? 'no `spec` field' : `spec=${describe(spec)}`;\n throw new Error(\n `Not an autotel architecture snapshot: ${path} (expected spec to start with \"${EXPECTED_SPEC_PREFIX}\", got ${found})`,\n );\n }\n\n // Order matters: the existing CLI surfaces \"missing events\" before\n // any other field-level errors, so users see the most useful diagnostic\n // first. The optional-required checks come after, only if events parsed.\n if (!isJsonObject(parsed.events)) {\n throw new Error(`Snapshot is missing required \\`events\\` map: ${path}`);\n }\n\n if (typeof parsed.service !== 'string' || parsed.service.length === 0) {\n throw new Error(`Snapshot is missing required \\`service\\` name: ${path}`);\n }\n\n if (typeof parsed.generatedAt !== 'string') {\n throw new Error(\n `Snapshot is missing required \\`generatedAt\\` (ISO 8601 string): ${path}`,\n );\n }\n\n for (const [name, observation] of Object.entries(parsed.events)) {\n if (!isJsonObject(observation)) {\n throw new Error(\n `Snapshot event \"${name}\" must be an object: ${path} (got ${describe(observation)})`,\n );\n }\n if (typeof observation.observedCount !== 'number') {\n throw new Error(\n `Snapshot event \"${name}\" is missing required \\`observedCount\\`: ${path}`,\n );\n }\n }\n\n return parsed as unknown as ArchitectureSnapshot;\n}\n\nfunction isJsonObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isNodeFsError(err: unknown): err is NodeJS.ErrnoException {\n return (\n err instanceof Error &&\n typeof (err as NodeJS.ErrnoException).code === 'string'\n );\n}\n\nfunction describe(value: unknown): string {\n if (value === null) return 'null';\n if (Array.isArray(value)) return 'array';\n return typeof value === 'string' ? JSON.stringify(value) : typeof value;\n}\n","// Read the current state of an EventCatalog using @eventcatalog/sdk. We\n// re-use SDK types (`Event`, `Service`, `Channel`) verbatim and only add the\n// two fields the SDK doesn't expose: the resolved on-disk `filePath`, and the\n// dotted field-path + schema-constraint extractions our drift diff consumes.\n// Inventing our own catalog types would silently drift from the SDK as it\n// evolves.\n\nimport utils from '@eventcatalog/sdk';\nimport type { Channel, Event, Service } from '@eventcatalog/sdk';\n\nexport type SchemaConstraint = {\n types?: string[];\n enumValues?: unknown[];\n};\n\nexport type CatalogEvent = Event & {\n /** Absolute path to the event's `index.mdx`, resolved via SDK. */\n filePath: string;\n /** Field paths declared in the event's JSON Schema (if present). */\n declaredFieldPaths?: string[];\n declaredSchemaConstraints?: Record<string, SchemaConstraint>;\n};\n\nexport type CatalogService = Service & {\n filePath: string;\n};\n\nexport type CatalogChannel = Channel & {\n filePath: string;\n};\n\nexport type CatalogState = {\n events: Map<string, CatalogEvent>;\n services: Map<string, CatalogService>;\n channels: Map<string, CatalogChannel>;\n};\n\nexport async function readCatalogState(\n catalogPath: string,\n): Promise<CatalogState> {\n const sdk = utils(catalogPath);\n\n const [events, services, channels] = await Promise.all([\n sdk.getEvents({ latestOnly: true, attachSchema: true }),\n sdk.getServices({ latestOnly: true }),\n sdk.getChannels({ latestOnly: true }),\n ]);\n\n const state: CatalogState = {\n events: new Map(),\n services: new Map(),\n channels: new Map(),\n };\n\n // SDK quirk (as of 2.21.2): unlike the other helpers, `getResourcePath` is\n // not curried with `catalogDir`, so we pass the catalog path explicitly.\n const resolveFilePath = async (id: string, version?: string) => {\n const paths = await sdk.getResourcePath(catalogPath, id, version);\n return paths?.fullPath ?? '';\n };\n\n for (const e of events ?? []) {\n const filePath = await resolveFilePath(e.id, e.version);\n const schemaExtractions = e.schema\n ? {\n declaredFieldPaths: extractDeclaredFieldPaths(e.schema),\n declaredSchemaConstraints: extractDeclaredSchemaConstraints(e.schema),\n }\n : {};\n state.events.set(e.id, { ...e, filePath, ...schemaExtractions });\n }\n\n for (const s of services ?? []) {\n const filePath = await resolveFilePath(s.id, s.version);\n state.services.set(s.id, { ...s, filePath });\n }\n\n for (const c of channels ?? []) {\n const filePath = await resolveFilePath(c.id, c.version);\n state.channels.set(c.id, { ...c, filePath });\n }\n\n return state;\n}\n\n/**\n * Extract field paths from a JSON Schema. Mirrors the dotted-path convention\n * used by the snapshot subscriber: arrays collapse to `[]`, nested objects\n * use `.`. We walk `properties` (objects) and `items` (arrays).\n */\nexport function extractDeclaredFieldPaths(\n schema: unknown,\n prefix = '',\n): string[] {\n const out = new Set<string>();\n walkSchema(schema, prefix, out);\n return [...out].toSorted();\n}\n\nfunction walkSchema(schema: unknown, prefix: string, out: Set<string>): void {\n if (!schema || typeof schema !== 'object') return;\n const s = schema as Record<string, unknown>;\n\n if (s.properties && typeof s.properties === 'object') {\n for (const [key, sub] of Object.entries(\n s.properties as Record<string, unknown>,\n )) {\n const path = prefix === '' ? key : `${prefix}.${key}`;\n out.add(path);\n walkSchema(sub, path, out);\n }\n }\n\n if (s.items) {\n const arrayPrefix = prefix + '[]';\n walkSchema(s.items, arrayPrefix, out);\n }\n}\n\nexport function extractDeclaredSchemaConstraints(\n schema: unknown,\n prefix = '',\n): Record<string, SchemaConstraint> {\n const out = new Map<string, SchemaConstraint>();\n walkSchemaConstraints(schema, prefix, out);\n const obj: Record<string, SchemaConstraint> = {};\n for (const [path, c] of out) obj[path] = c;\n return obj;\n}\n\nfunction walkSchemaConstraints(\n schema: unknown,\n prefix: string,\n out: Map<string, SchemaConstraint>,\n): void {\n if (!schema || typeof schema !== 'object') return;\n const s = schema as Record<string, unknown>;\n const typeVal = s.type;\n const enumVal = s.enum;\n if (prefix !== '' && (typeVal !== undefined || enumVal !== undefined)) {\n const types = toTypeArray(typeVal);\n const enumValues = Array.isArray(enumVal) ? [...enumVal] : undefined;\n out.set(prefix, {\n ...(types.length > 0 ? { types } : {}),\n ...(enumValues ? { enumValues } : {}),\n });\n }\n\n if (s.properties && typeof s.properties === 'object') {\n for (const [key, sub] of Object.entries(\n s.properties as Record<string, unknown>,\n )) {\n const path = prefix === '' ? key : `${prefix}.${key}`;\n walkSchemaConstraints(sub, path, out);\n }\n }\n if (s.items) {\n const arrayPrefix = prefix + '[]';\n walkSchemaConstraints(s.items, arrayPrefix, out);\n }\n}\n\nfunction toTypeArray(typeVal: unknown): string[] {\n if (typeof typeVal === 'string') return [typeVal];\n if (Array.isArray(typeVal)) {\n return typeVal.filter((t): t is string => typeof t === 'string').toSorted();\n }\n return [];\n}\n","// Compute drift between an autotel architecture snapshot and an existing\n// EventCatalog. The diff covers five drift classes:\n// - event existence (observedButUndocumented, documentedButUnseen)\n// - field-path drift (extras and missing per event)\n// - type drift (declared primitive type vs observed runtime types)\n// - value drift (declared enum vs observed sample values)\n// - service and channel existence drift\n\nimport type { ArchitectureSnapshot } from './snapshot';\nimport type { CatalogState } from './catalog';\n\nexport type EventDrift = {\n /** Event names observed in the snapshot but not present in the catalog. */\n observedButUndocumented: string[];\n /** Event names declared in the catalog but never observed in the snapshot. */\n documentedButUnseen: string[];\n /** Per-event field-path mismatches. */\n fieldDrift: FieldDrift[];\n /** Per-event field type mismatches against declared schema types. */\n typeDrift: TypeDrift[];\n /** Per-event enum/value mismatches against declared schema enums. */\n valueDrift: ValueDrift[];\n};\n\nexport type FieldDrift = {\n event: string;\n /** Field paths in the observed payload but not declared in the schema. */\n extra: string[];\n /** Field paths declared in the schema but never observed in a payload. */\n missing: string[];\n};\n\nexport type TypeDrift = {\n event: string;\n path: string;\n declared: string[];\n observed: string[];\n};\n\nexport type ValueDrift = {\n event: string;\n path: string;\n declared: unknown[];\n observed: unknown[];\n};\n\nexport type ServiceDrift = {\n /** Producers in the snapshot but not present in the catalog as services. */\n observedButUndocumented: string[];\n};\n\nexport type ChannelDrift = {\n /** Channels in the snapshot but not present in the catalog. */\n observedButUndocumented: string[];\n};\n\nexport type DriftReport = {\n snapshotGeneratedAt: string;\n snapshotService: string;\n events: EventDrift;\n services: ServiceDrift;\n channels: ChannelDrift;\n};\n\n/** True if the report contains any drift worth surfacing in a PR check. */\nexport function hasDrift(report: DriftReport): boolean {\n const c = countDriftReport(report);\n return c.total > 0;\n}\n\n/**\n * Per-category counts for a DriftReport. Keeps the dashboard's hero meter,\n * the CLI's summary-output, and the action's structured output all agreeing\n * on what \"N findings\" means.\n */\nexport type DriftCounts = {\n /** Total of all categories; what a dashboard \"drift findings\" badge shows. */\n total: number;\n observedButUndocumentedEvents: number;\n documentedButUnseenEvents: number;\n /** Number of distinct events with field-path drift entries. */\n fieldDriftEvents: number;\n /** Sum of every individual extra + missing path across all fieldDrift entries. */\n fieldDriftPaths: number;\n typeDriftPaths: number;\n valueDriftPaths: number;\n undocumentedServices: number;\n undocumentedChannels: number;\n};\n\nexport function countDriftReport(report: DriftReport): DriftCounts {\n const typeDrift = report.events.typeDrift ?? [];\n const valueDrift = report.events.valueDrift ?? [];\n const fieldDriftEvents = report.events.fieldDrift.length;\n const fieldDriftPaths = report.events.fieldDrift.reduce(\n (sum, fd) => sum + fd.extra.length + fd.missing.length,\n 0,\n );\n const typeDriftPaths = typeDrift.length;\n const valueDriftPaths = valueDrift.length;\n const observedButUndocumentedEvents =\n report.events.observedButUndocumented.length;\n const documentedButUnseenEvents = report.events.documentedButUnseen.length;\n const undocumentedServices = report.services.observedButUndocumented.length;\n const undocumentedChannels = report.channels.observedButUndocumented.length;\n\n return {\n observedButUndocumentedEvents,\n documentedButUnseenEvents,\n fieldDriftEvents,\n fieldDriftPaths,\n typeDriftPaths,\n valueDriftPaths,\n undocumentedServices,\n undocumentedChannels,\n total:\n observedButUndocumentedEvents +\n documentedButUnseenEvents +\n fieldDriftPaths +\n typeDriftPaths +\n valueDriftPaths +\n undocumentedServices +\n undocumentedChannels,\n };\n}\n\nexport function diffCatalogAgainstSnapshot(\n snapshot: ArchitectureSnapshot,\n catalog: CatalogState,\n): DriftReport {\n const snapshotEvents = new Set(Object.keys(snapshot.events));\n const catalogEventIds = new Set(catalog.events.keys());\n\n // Catalog event IDs are PascalCase (\"OrderPlaced\") while track() names are\n // dotted (\"order.placed\"). We compare on a normalised form so the same\n // event isn't reported as both missing and extra.\n const catalogEventByNormalised = new Map<string, string>();\n for (const id of catalogEventIds) {\n catalogEventByNormalised.set(normaliseEventId(id), id);\n }\n\n const observedButUndocumented: string[] = [];\n const matchedCatalogIds = new Set<string>();\n for (const name of snapshotEvents) {\n const matched = catalogEventByNormalised.get(normaliseEventId(name));\n if (matched) {\n matchedCatalogIds.add(matched);\n } else {\n observedButUndocumented.push(name);\n }\n }\n\n const documentedButUnseen: string[] = [];\n for (const id of catalogEventIds) {\n if (!matchedCatalogIds.has(id)) documentedButUnseen.push(id);\n }\n\n const fieldDrift: FieldDrift[] = [];\n const typeDrift: TypeDrift[] = [];\n const valueDrift: ValueDrift[] = [];\n for (const [snapName, obs] of Object.entries(snapshot.events)) {\n const catalogId = catalogEventByNormalised.get(normaliseEventId(snapName));\n if (!catalogId) continue;\n const eventDecl = catalog.events.get(catalogId);\n const declared = eventDecl?.declaredFieldPaths;\n if (!declared) continue;\n\n const declaredSet = new Set(declared);\n const observedSet = new Set(obs.fieldPaths);\n\n const extra = obs.fieldPaths.filter((p) => !declaredSet.has(p));\n const missing = declared.filter((p) => !observedSet.has(p));\n\n if (extra.length > 0 || missing.length > 0) {\n fieldDrift.push({ event: snapName, extra, missing });\n }\n\n const constraints = eventDecl?.declaredSchemaConstraints ?? {};\n const stats = obs.fieldStats ?? {};\n for (const [path, declaredConstraint] of Object.entries(constraints)) {\n const observed = stats[path];\n if (!observed) continue;\n if (declaredConstraint.types && declaredConstraint.types.length > 0) {\n // JSON Schema has `integer`; JavaScript has only `number`. Treat the\n // two as compatible at the runtime-type level, then use sample values\n // to flag the real signal (a non-integer value seen against an\n // integer-only declaration).\n const accepts = expandDeclaredTypes(declaredConstraint.types);\n const badTypes = observed.types.filter((t: string) => !accepts.has(t));\n const integerDeclared =\n declaredConstraint.types.includes('integer') &&\n !declaredConstraint.types.includes('number');\n const nonIntegerSamples = integerDeclared\n ? observed.sampleValues.filter(\n (v: unknown) => typeof v === 'number' && !Number.isInteger(v),\n )\n : [];\n if (badTypes.length > 0 || nonIntegerSamples.length > 0) {\n typeDrift.push({\n event: snapName,\n path,\n declared: declaredConstraint.types,\n observed: [...new Set(observed.types)].toSorted(),\n });\n }\n }\n if (\n declaredConstraint.enumValues &&\n declaredConstraint.enumValues.length > 0 &&\n observed.sampleValues.length > 0\n ) {\n const observedOutsideEnum = observed.sampleValues.filter(\n (v: unknown) =>\n !declaredConstraint.enumValues?.some((d) => Object.is(d, v)),\n );\n if (observedOutsideEnum.length > 0) {\n valueDrift.push({\n event: snapName,\n path,\n declared: declaredConstraint.enumValues,\n observed: [...new Set(observedOutsideEnum)] as unknown[],\n });\n }\n }\n }\n }\n\n const snapshotServices = collectProducers(snapshot);\n const catalogServiceIds = new Set(catalog.services.keys());\n const undocumentedServices = [...snapshotServices].filter(\n (id) => !catalogServiceIds.has(id),\n );\n\n const snapshotChannels = collectChannels(snapshot);\n const catalogChannelIds = new Set(catalog.channels.keys());\n const undocumentedChannels = [...snapshotChannels].filter(\n (id) => !catalogChannelIds.has(id),\n );\n\n return {\n snapshotGeneratedAt: snapshot.generatedAt,\n snapshotService: snapshot.service,\n events: {\n observedButUndocumented: observedButUndocumented.sort(),\n documentedButUnseen: documentedButUnseen.sort(),\n fieldDrift: fieldDrift.sort((a, b) => a.event.localeCompare(b.event)),\n typeDrift: typeDrift.sort((a, b) =>\n `${a.event}.${a.path}`.localeCompare(`${b.event}.${b.path}`),\n ),\n valueDrift: valueDrift.sort((a, b) =>\n `${a.event}.${a.path}`.localeCompare(`${b.event}.${b.path}`),\n ),\n },\n services: { observedButUndocumented: undocumentedServices.sort() },\n channels: { observedButUndocumented: undocumentedChannels.sort() },\n };\n}\n\n/**\n * Map declared JSON Schema types to the set of runtime types we accept at\n * `typeof` level. JSON Schema's `integer` is a refinement of `number` (JS\n * does not have a separate integer type), so we accept observed `number` for\n * either declaration. The integer-vs-fractional distinction is then enforced\n * separately against sample values.\n */\nfunction expandDeclaredTypes(declared: string[]): Set<string> {\n const accepts = new Set<string>(declared);\n if (declared.includes('integer')) accepts.add('number');\n return accepts;\n}\n\nfunction normaliseEventId(id: string): string {\n // \"order.placed\" -> \"orderplaced\", \"OrderPlaced\" -> \"orderplaced\".\n return id.toLowerCase().replaceAll(/[._\\-\\s]/g, '');\n}\n\nfunction collectProducers(snapshot: ArchitectureSnapshot): Set<string> {\n const out = new Set<string>();\n for (const obs of Object.values(snapshot.events)) {\n if (obs.producer) out.add(obs.producer);\n }\n return out;\n}\n\nfunction collectChannels(snapshot: ArchitectureSnapshot): Set<string> {\n const out = new Set<string>();\n for (const obs of Object.values(snapshot.events)) {\n if (obs.channel) out.add(obs.channel);\n }\n return out;\n}\n","// Compare two drift reports (base branch vs PR head) and produce a \"what\n// this PR introduces\" view. Without this, a PR check fails forever on\n// pre-existing drift; with it, the check only fails on drift the PR is\n// responsible for.\n\nimport type {\n DriftReport,\n FieldDrift,\n DriftCounts,\n TypeDrift,\n ValueDrift,\n} from './diff';\n\nexport type DriftDelta = {\n /** Drift entries present in head but not in base. */\n introduced: DriftEntries;\n /** Drift entries present in base but not in head; the PR fixed these. */\n resolved: DriftEntries;\n /** True if `introduced` has any non-empty section. */\n hasNewDrift: boolean;\n};\n\nexport type DriftEntries = {\n events: {\n observedButUndocumented: string[];\n documentedButUnseen: string[];\n fieldDrift: FieldDrift[];\n typeDrift: TypeDrift[];\n valueDrift: ValueDrift[];\n };\n services: { observedButUndocumented: string[] };\n channels: { observedButUndocumented: string[] };\n};\n\nexport function compareDriftReports(\n base: DriftReport,\n head: DriftReport,\n): DriftDelta {\n const introducedEvents = diffStringList(\n base.events.observedButUndocumented,\n head.events.observedButUndocumented,\n );\n const introducedMissing = diffStringList(\n base.events.documentedButUnseen,\n head.events.documentedButUnseen,\n );\n const introducedFieldDrift = diffFieldDrift(\n base.events.fieldDrift,\n head.events.fieldDrift,\n );\n const introducedServices = diffStringList(\n base.services.observedButUndocumented,\n head.services.observedButUndocumented,\n );\n const introducedChannels = diffStringList(\n base.channels.observedButUndocumented,\n head.channels.observedButUndocumented,\n );\n\n const introduced: DriftEntries = {\n events: {\n observedButUndocumented: introducedEvents.added,\n documentedButUnseen: introducedMissing.added,\n fieldDrift: introducedFieldDrift.added,\n typeDrift: diffTypeDrift(\n base.events.typeDrift ?? [],\n head.events.typeDrift ?? [],\n ).added,\n valueDrift: diffValueDrift(\n base.events.valueDrift ?? [],\n head.events.valueDrift ?? [],\n ).added,\n },\n services: { observedButUndocumented: introducedServices.added },\n channels: { observedButUndocumented: introducedChannels.added },\n };\n\n const resolved: DriftEntries = {\n events: {\n observedButUndocumented: introducedEvents.removed,\n documentedButUnseen: introducedMissing.removed,\n fieldDrift: introducedFieldDrift.removed,\n typeDrift: diffTypeDrift(\n base.events.typeDrift ?? [],\n head.events.typeDrift ?? [],\n ).removed,\n valueDrift: diffValueDrift(\n base.events.valueDrift ?? [],\n head.events.valueDrift ?? [],\n ).removed,\n },\n services: { observedButUndocumented: introducedServices.removed },\n channels: { observedButUndocumented: introducedChannels.removed },\n };\n\n const hasNewDrift =\n introduced.events.observedButUndocumented.length > 0 ||\n introduced.events.documentedButUnseen.length > 0 ||\n introduced.events.fieldDrift.length > 0 ||\n introduced.events.typeDrift.length > 0 ||\n introduced.events.valueDrift.length > 0 ||\n introduced.services.observedButUndocumented.length > 0 ||\n introduced.channels.observedButUndocumented.length > 0;\n\n return { introduced, resolved, hasNewDrift };\n}\n\n/**\n * Per-category counts for one side of a DriftDelta (introduced or resolved).\n * Same shape as DriftCounts so dashboards and CI can render the\n * introduced/resolved sections with identical accounting.\n */\nexport function countDriftEntries(entries: DriftEntries): DriftCounts {\n const fieldDriftEvents = entries.events.fieldDrift.length;\n const fieldDriftPaths = entries.events.fieldDrift.reduce(\n (sum, fd) => sum + fd.extra.length + fd.missing.length,\n 0,\n );\n const observedButUndocumentedEvents =\n entries.events.observedButUndocumented.length;\n const documentedButUnseenEvents = entries.events.documentedButUnseen.length;\n const undocumentedServices = entries.services.observedButUndocumented.length;\n const undocumentedChannels = entries.channels.observedButUndocumented.length;\n const typeDriftPaths = (entries.events.typeDrift ?? []).length;\n const valueDriftPaths = (entries.events.valueDrift ?? []).length;\n\n return {\n observedButUndocumentedEvents,\n documentedButUnseenEvents,\n fieldDriftEvents,\n fieldDriftPaths,\n typeDriftPaths,\n valueDriftPaths,\n undocumentedServices,\n undocumentedChannels,\n total:\n observedButUndocumentedEvents +\n documentedButUnseenEvents +\n fieldDriftPaths +\n typeDriftPaths +\n valueDriftPaths +\n undocumentedServices +\n undocumentedChannels,\n };\n}\n\nexport function countDriftDelta(delta: DriftDelta): {\n introduced: DriftCounts;\n resolved: DriftCounts;\n} {\n return {\n introduced: countDriftEntries(delta.introduced),\n resolved: countDriftEntries(delta.resolved),\n };\n}\n\nfunction diffStringList(\n base: string[],\n head: string[],\n): { added: string[]; removed: string[] } {\n const baseSet = new Set(base);\n const headSet = new Set(head);\n return {\n added: head.filter((s) => !baseSet.has(s)).sort(),\n removed: base.filter((s) => !headSet.has(s)).sort(),\n };\n}\n\nfunction diffFieldDrift(\n base: FieldDrift[],\n head: FieldDrift[],\n): { added: FieldDrift[]; removed: FieldDrift[] } {\n const baseByEvent = new Map(base.map((d) => [d.event, d]));\n const headByEvent = new Map(head.map((d) => [d.event, d]));\n\n const added: FieldDrift[] = [];\n const removed: FieldDrift[] = [];\n\n for (const [event, h] of headByEvent) {\n const b = baseByEvent.get(event);\n if (!b) {\n // Entire event's field drift is new to head.\n added.push(h);\n continue;\n }\n const addedExtra = h.extra.filter((p) => !b.extra.includes(p));\n const addedMissing = h.missing.filter((p) => !b.missing.includes(p));\n if (addedExtra.length > 0 || addedMissing.length > 0) {\n added.push({ event, extra: addedExtra, missing: addedMissing });\n }\n }\n\n for (const [event, b] of baseByEvent) {\n const h = headByEvent.get(event);\n if (!h) {\n removed.push(b);\n continue;\n }\n const removedExtra = b.extra.filter((p) => !h.extra.includes(p));\n const removedMissing = b.missing.filter((p) => !h.missing.includes(p));\n if (removedExtra.length > 0 || removedMissing.length > 0) {\n removed.push({ event, extra: removedExtra, missing: removedMissing });\n }\n }\n\n return { added, removed };\n}\n\nfunction diffTypeDrift(\n base: TypeDrift[],\n head: TypeDrift[],\n): { added: TypeDrift[]; removed: TypeDrift[] } {\n return diffStructuredByKey(base, head, (x) => `${x.event}::${x.path}`);\n}\n\nfunction diffValueDrift(\n base: ValueDrift[],\n head: ValueDrift[],\n): { added: ValueDrift[]; removed: ValueDrift[] } {\n return diffStructuredByKey(base, head, (x) => `${x.event}::${x.path}`);\n}\n\nfunction diffStructuredByKey<T>(\n base: T[],\n head: T[],\n keyOf: (v: T) => string,\n): { added: T[]; removed: T[] } {\n const baseMap = new Map(base.map((v) => [keyOf(v), v]));\n const headMap = new Map(head.map((v) => [keyOf(v), v]));\n const added: T[] = [];\n const removed: T[] = [];\n\n for (const [k, hv] of headMap) {\n const bv = baseMap.get(k);\n if (!bv || JSON.stringify(bv) !== JSON.stringify(hv)) added.push(hv);\n }\n for (const [k, bv] of baseMap) {\n const hv = headMap.get(k);\n if (!hv || JSON.stringify(hv) !== JSON.stringify(bv)) removed.push(bv);\n }\n return { added, removed };\n}\n","// GitHub-flavoured Markdown; the default. Used directly as the body of\n// the sticky PR comment posted by the bundled action.\n\nimport type { DriftReport, FieldDrift } from '../diff';\nimport { hasDrift } from '../diff';\nimport type { DriftDelta, DriftEntries } from '../diff-vs-base';\nimport type { Renderer } from './types';\n\nexport function renderMarkdown(report: DriftReport): string {\n const lines: string[] = [\n '# Architecture drift report',\n '',\n `_Snapshot from \\`${report.snapshotService}\\` at ${report.snapshotGeneratedAt}_`,\n '',\n ];\n\n if (!hasDrift(report)) {\n lines.push('No drift detected. Catalog and runtime agree.', '');\n return lines.join('\\n');\n }\n\n if (report.events.observedButUndocumented.length > 0) {\n lines.push(\n '## Events observed but undocumented',\n '',\n 'These event names appear in the snapshot but no matching entry',\n 'exists in the catalog. Add them or stop emitting them.',\n '',\n );\n for (const name of report.events.observedButUndocumented) {\n lines.push(`- \\`${name}\\``);\n }\n lines.push('');\n }\n\n if (report.events.documentedButUnseen.length > 0) {\n lines.push(\n '## Events documented but never observed',\n '',\n 'These events exist in the catalog but no payload was captured.',\n 'Either the tests do not exercise this event, or it has been removed.',\n '',\n );\n for (const name of report.events.documentedButUnseen) {\n lines.push(`- \\`${name}\\``);\n }\n lines.push('');\n }\n\n if (report.events.fieldDrift.length > 0) {\n lines.push('## Field-path drift', '');\n for (const drift of report.events.fieldDrift) {\n lines.push(`### \\`${drift.event}\\``, '');\n if (drift.extra.length > 0) {\n lines.push(\n '**Extra fields in payloads (not in declared schema):**',\n '',\n );\n for (const p of drift.extra) lines.push(`- \\`${p}\\``);\n lines.push('');\n }\n if (drift.missing.length > 0) {\n lines.push('**Fields declared but never observed:**', '');\n for (const p of drift.missing) lines.push(`- \\`${p}\\``);\n lines.push('');\n }\n }\n }\n\n if ((report.events.typeDrift ?? []).length > 0) {\n lines.push('## Type drift', '');\n for (const drift of report.events.typeDrift ?? []) {\n lines.push(\n `- \\`${drift.event}\\` \\`${drift.path}\\``,\n ` declared: \\`${drift.declared.join(' | ')}\\`, observed: \\`${drift.observed.join(' | ')}\\``,\n );\n }\n lines.push('');\n }\n\n if ((report.events.valueDrift ?? []).length > 0) {\n lines.push('## Value drift', '');\n for (const drift of report.events.valueDrift ?? []) {\n lines.push(\n `- \\`${drift.event}\\` \\`${drift.path}\\``,\n ` declared enum: \\`${drift.declared.map((v) => JSON.stringify(v)).join(', ')}\\`, observed: \\`${drift.observed.map((v) => JSON.stringify(v)).join(', ')}\\``,\n );\n }\n lines.push('');\n }\n\n if (report.services.observedButUndocumented.length > 0) {\n lines.push('## Services observed but undocumented', '');\n for (const id of report.services.observedButUndocumented) {\n lines.push(`- \\`${id}\\``);\n }\n lines.push('');\n }\n\n if (report.channels.observedButUndocumented.length > 0) {\n lines.push('## Channels observed but undocumented', '');\n for (const id of report.channels.observedButUndocumented) {\n lines.push(`- \\`${id}\\``);\n }\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Render the diff-of-diffs as a PR-comment-friendly markdown block. Sections\n * appear only when they have content, so a clean PR produces a tight message.\n */\nexport function renderDeltaMarkdown(delta: DriftDelta): string {\n const lines: string[] = [\n '# Architecture drift; what this change introduces',\n '',\n ];\n\n if (!delta.hasNewDrift) {\n const fixedAny = entriesHasContent(delta.resolved);\n if (fixedAny) {\n lines.push('No new drift. The changes below resolve existing drift:', '');\n renderEntries(delta.resolved, lines, { sign: '−' });\n } else {\n lines.push('No new drift detected. Catalog and runtime agree.');\n }\n lines.push('');\n return lines.join('\\n');\n }\n\n lines.push('This change introduces drift:', '');\n renderEntries(delta.introduced, lines, { sign: '+' });\n\n if (entriesHasContent(delta.resolved)) {\n lines.push('', '### Resolved by this change', '');\n renderEntries(delta.resolved, lines, { sign: '−' });\n }\n\n return lines.join('\\n');\n}\n\nfunction entriesHasContent(e: DriftEntries): boolean {\n return (\n e.events.observedButUndocumented.length > 0 ||\n e.events.documentedButUnseen.length > 0 ||\n e.events.fieldDrift.length > 0 ||\n (e.events.typeDrift ?? []).length > 0 ||\n (e.events.valueDrift ?? []).length > 0 ||\n e.services.observedButUndocumented.length > 0 ||\n e.channels.observedButUndocumented.length > 0\n );\n}\n\nfunction renderEntries(\n entries: DriftEntries,\n out: string[],\n options: { sign: '+' | '−' },\n): void {\n if (entries.events.observedButUndocumented.length > 0) {\n out.push('**Events observed but undocumented**', '');\n for (const n of entries.events.observedButUndocumented) {\n out.push(`- \\`${n}\\``);\n }\n out.push('');\n }\n if (entries.events.documentedButUnseen.length > 0) {\n out.push('**Events documented but never observed**', '');\n for (const n of entries.events.documentedButUnseen) {\n out.push(`- \\`${n}\\``);\n }\n out.push('');\n }\n for (const fd of entries.events.fieldDrift) {\n out.push(`**Field drift on \\`${fd.event}\\`**`, '');\n for (const p of fd.extra) out.push(`- ${options.sign} \\`${p}\\` (extra)`);\n for (const p of fd.missing)\n out.push(`- ${options.sign} \\`${p}\\` (missing)`);\n out.push('');\n }\n for (const td of entries.events.typeDrift ?? []) {\n out.push(\n `**Type drift on \\`${td.event}\\` \\`${td.path}\\`**`,\n '',\n `- ${options.sign} declared \\`${td.declared.join(' | ')}\\`, observed \\`${td.observed.join(' | ')}\\``,\n '',\n );\n }\n for (const vd of entries.events.valueDrift ?? []) {\n out.push(\n `**Value drift on \\`${vd.event}\\` \\`${vd.path}\\`**`,\n '',\n `- ${options.sign} declared enum \\`${vd.declared.map((v) => JSON.stringify(v)).join(', ')}\\`, observed \\`${vd.observed.map((v) => JSON.stringify(v)).join(', ')}\\``,\n '',\n );\n }\n if (entries.services.observedButUndocumented.length > 0) {\n out.push('**Services observed but undocumented**', '');\n for (const id of entries.services.observedButUndocumented) {\n out.push(`- \\`${id}\\``);\n }\n out.push('');\n }\n if (entries.channels.observedButUndocumented.length > 0) {\n out.push('**Channels observed but undocumented**', '');\n for (const id of entries.channels.observedButUndocumented) {\n out.push(`- \\`${id}\\``);\n }\n out.push('');\n }\n // FieldDrift import kept for typing of the for..of above; reference here so\n // the import isn't flagged as unused by some linter configurations.\n void (null as unknown as FieldDrift);\n}\n\nexport const markdownRenderer: Renderer = {\n name: 'markdown',\n description:\n 'GitHub-flavoured Markdown (default). Suitable for sticky PR comments.',\n renderReport: renderMarkdown,\n renderDelta: renderDeltaMarkdown,\n};\n","// Plain-text rendering; for terminals, log files, Slack messages, anywhere\n// markdown decorations would render as noise. Reuses the markdown renderer\n// and strips heading marks, inline code backticks, and bold emphasis.\n\nimport type { DriftReport } from '../diff';\nimport type { DriftDelta } from '../diff-vs-base';\nimport { renderMarkdown, renderDeltaMarkdown } from './markdown';\nimport type { Renderer } from './types';\n\nexport function renderTerminal(report: DriftReport): string {\n return stripMarkdownDecorations(renderMarkdown(report));\n}\n\nexport function renderDeltaTerminal(delta: DriftDelta): string {\n return stripMarkdownDecorations(renderDeltaMarkdown(delta));\n}\n\nfunction stripMarkdownDecorations(md: string): string {\n return md\n .replaceAll(/^#+\\s+/gm, '')\n .replaceAll('`', '')\n .replaceAll(/\\*\\*([^*]+)\\*\\*/g, '$1');\n}\n\nexport const terminalRenderer: Renderer = {\n name: 'terminal',\n description: 'Plain text. Same content as markdown, decorations stripped.',\n renderReport: renderTerminal,\n renderDelta: renderDeltaTerminal,\n};\n","// Versioned JSON envelope. Downstream tooling (dashboards, custom CI steps,\n// Slack bots) should read this rather than scraping the Markdown body. The\n// shape is governed by the published schema at\n// `schemas/drift-report-v0.2.0.json` and locked by golden contract tests.\n\nimport type { DriftReport } from '../diff';\nimport type { DriftDelta } from '../diff-vs-base';\nimport type { Renderer } from './types';\n\n/**\n * Versioned identifier baked into the JSON envelope. Bumping it is a\n * breaking change for downstream consumers; add fields rather than rename.\n */\nexport const REPORT_SPEC = 'autotel-eventcatalog-report/v0.2.0' as const;\n\nexport type JsonReport =\n | { mode: 'all'; report: DriftReport }\n | { mode: 'new-only'; delta: DriftDelta };\n\nexport type JsonReportEnvelope = { spec: typeof REPORT_SPEC } & JsonReport;\n\nexport function renderJson(data: JsonReport): string {\n const envelope: JsonReportEnvelope = { spec: REPORT_SPEC, ...data };\n return JSON.stringify(envelope, null, 2);\n}\n\nexport const jsonRenderer: Renderer = {\n name: 'json',\n description:\n 'Versioned JSON envelope. Validate against schemas/drift-report-v0.2.0.json.',\n renderReport: (report) => renderJson({ mode: 'all', report }),\n renderDelta: (delta) => renderJson({ mode: 'new-only', delta }),\n};\n","import type { DriftReport } from './diff';\nimport type { DriftDelta, DriftEntries } from './diff-vs-base';\n\nexport type SnapshotResourceType =\n 'event' | 'command' | 'query' | 'service' | 'domain' | 'channel';\n\nexport type ResourceChangeType = 'added' | 'removed' | 'modified' | 'versioned';\n\nexport type ResourceChange = {\n resourceId: string;\n version: string;\n type: SnapshotResourceType;\n changeType: ResourceChangeType;\n changedFields?: string[];\n previousVersion?: string;\n newVersion?: string;\n};\n\nexport type RelationshipChange = {\n serviceId: string;\n serviceVersion: string;\n resourceId: string;\n resourceVersion?: string;\n direction: 'sends' | 'receives';\n changeType: 'added' | 'removed';\n};\n\nexport type EventCatalogSnapshotDiff = {\n snapshotA: { label: string; createdAt: string };\n snapshotB: { label: string; createdAt: string };\n summary: {\n totalChanges: number;\n resourcesAdded: number;\n resourcesRemoved: number;\n resourcesModified: number;\n resourcesVersioned: number;\n relationshipsAdded: number;\n relationshipsRemoved: number;\n };\n resources: ResourceChange[];\n relationships: RelationshipChange[];\n};\n\nexport function toSnapshotDiffFromReport(\n report: DriftReport,\n): EventCatalogSnapshotDiff {\n const entries: DriftEntries = {\n events: report.events,\n services: report.services,\n channels: report.channels,\n };\n return snapshotDiffForEntries(entries, report.snapshotGeneratedAt, 'runtime');\n}\n\nexport function toSnapshotDiffFromDelta(\n delta: DriftDelta,\n): EventCatalogSnapshotDiff {\n return snapshotDiffForEntries(\n delta.introduced,\n new Date(0).toISOString(),\n 'runtime:new-drift',\n );\n}\n\nfunction snapshotDiffForEntries(\n entries: DriftEntries,\n createdAt: string,\n label: string,\n): EventCatalogSnapshotDiff {\n const resources: ResourceChange[] = [];\n const relationships: RelationshipChange[] = [];\n\n for (const eventName of entries.events.observedButUndocumented) {\n resources.push({\n resourceId: eventName,\n version: 'runtime',\n type: 'event',\n changeType: 'added',\n });\n }\n\n for (const eventName of entries.events.documentedButUnseen) {\n resources.push({\n resourceId: eventName,\n version: 'runtime',\n type: 'event',\n changeType: 'removed',\n });\n }\n\n for (const drift of entries.events.fieldDrift) {\n resources.push({\n resourceId: drift.event,\n version: 'runtime',\n type: 'event',\n changeType: 'modified',\n changedFields: [\n ...drift.extra.map((p) => `extra:${p}`),\n ...drift.missing.map((p) => `missing:${p}`),\n ],\n });\n }\n\n for (const drift of entries.events.typeDrift ?? []) {\n resources.push({\n resourceId: drift.event,\n version: 'runtime',\n type: 'event',\n changeType: 'modified',\n changedFields: [`type:${drift.path}`],\n });\n }\n\n for (const drift of entries.events.valueDrift ?? []) {\n resources.push({\n resourceId: drift.event,\n version: 'runtime',\n type: 'event',\n changeType: 'modified',\n changedFields: [`enum:${drift.path}`],\n });\n }\n\n for (const serviceId of entries.services.observedButUndocumented) {\n resources.push({\n resourceId: serviceId,\n version: 'runtime',\n type: 'service',\n changeType: 'added',\n });\n }\n\n for (const channelId of entries.channels.observedButUndocumented) {\n resources.push({\n resourceId: channelId,\n version: 'runtime',\n type: 'channel',\n changeType: 'added',\n });\n }\n\n const summary = {\n totalChanges: resources.length + relationships.length,\n resourcesAdded: resources.filter((r) => r.changeType === 'added').length,\n resourcesRemoved: resources.filter((r) => r.changeType === 'removed')\n .length,\n resourcesModified: resources.filter((r) => r.changeType === 'modified')\n .length,\n resourcesVersioned: resources.filter((r) => r.changeType === 'versioned')\n .length,\n relationshipsAdded: relationships.filter((r) => r.changeType === 'added')\n .length,\n relationshipsRemoved: relationships.filter(\n (r) => r.changeType === 'removed',\n ).length,\n };\n\n return {\n snapshotA: { label: 'catalog', createdAt: new Date(0).toISOString() },\n snapshotB: { label, createdAt },\n summary,\n resources,\n relationships,\n };\n}\n","import type { Renderer } from './types';\nimport type { DriftReport } from '../diff';\nimport type { DriftDelta } from '../diff-vs-base';\nimport {\n toSnapshotDiffFromDelta,\n toSnapshotDiffFromReport,\n} from '../eventcatalog-snapshot-diff';\n\nexport const EVENTCATALOG_SNAPSHOT_DIFF_SPEC =\n 'autotel-eventcatalog-snapshot-diff/v0.1.0' as const;\n\nexport type EventCatalogSnapshotDiffEnvelope = {\n spec: typeof EVENTCATALOG_SNAPSHOT_DIFF_SPEC;\n mode: 'all' | 'new-only';\n diff: ReturnType<typeof toSnapshotDiffFromReport>;\n};\n\nexport function renderEventCatalogSnapshotDiffFromReport(\n report: DriftReport,\n): string {\n const envelope: EventCatalogSnapshotDiffEnvelope = {\n spec: EVENTCATALOG_SNAPSHOT_DIFF_SPEC,\n mode: 'all',\n diff: toSnapshotDiffFromReport(report),\n };\n return JSON.stringify(envelope, null, 2);\n}\n\nexport function renderEventCatalogSnapshotDiffFromDelta(\n delta: DriftDelta,\n): string {\n const envelope: EventCatalogSnapshotDiffEnvelope = {\n spec: EVENTCATALOG_SNAPSHOT_DIFF_SPEC,\n mode: 'new-only',\n diff: toSnapshotDiffFromDelta(delta),\n };\n return JSON.stringify(envelope, null, 2);\n}\n\nexport const eventcatalogSnapshotDiffRenderer: Renderer = {\n name: 'eventcatalog-snapshot-diff',\n description:\n 'EventCatalog SnapshotDiff-compatible JSON for catalog-native drift views.',\n renderReport: renderEventCatalogSnapshotDiffFromReport,\n renderDelta: renderEventCatalogSnapshotDiffFromDelta,\n};\n","// Registry of available renderers. The CLI dispatches `--format <name>`\n// through here; future renderers (sarif, slack, github-check-runs) drop in\n// by adding an entry to `RENDERERS`.\n\nimport type { Renderer } from './types';\nimport { markdownRenderer } from './markdown';\nimport { terminalRenderer } from './terminal';\nimport { jsonRenderer } from './json';\nimport { eventcatalogSnapshotDiffRenderer } from './eventcatalog-snapshot-diff';\n\nconst BUILTIN_RENDERERS: readonly Renderer[] = [\n markdownRenderer,\n terminalRenderer,\n jsonRenderer,\n eventcatalogSnapshotDiffRenderer,\n];\n\nconst extraRenderers: Renderer[] = [];\n\n/**\n * @deprecated Use `listRenderers()` for the full registry (built-ins plus\n * any registered at runtime). Kept for backwards compatibility.\n */\nexport const RENDERERS: readonly Renderer[] = BUILTIN_RENDERERS;\n\n/**\n * Names of the built-in renderers, narrowed to a string literal union via\n * `as const`. Custom renderers registered via `registerRenderer` widen the\n * runtime set but not this type; the CLI uses `listRendererNames()` for\n * runtime listings.\n */\nexport const RENDERER_NAMES = [\n 'markdown',\n 'terminal',\n 'json',\n 'eventcatalog-snapshot-diff',\n] as const;\n\nexport type RendererName = (typeof RENDERER_NAMES)[number];\n\nexport function getRenderer(name: string): Renderer | undefined {\n return listRenderers().find((r) => r.name === name);\n}\n\nexport function listRenderers(): readonly Renderer[] {\n return [...BUILTIN_RENDERERS, ...extraRenderers];\n}\n\nexport function listRendererNames(): readonly string[] {\n return listRenderers().map((r) => r.name);\n}\n\n/**\n * Register a custom renderer at runtime. The CLI calls this when a\n * `--register-renderer <module>` flag is supplied; library users may call\n * it directly before invoking `runDrift`/`runStamp`/`runGenerate`.\n */\nexport function registerRenderer(renderer: Renderer): void {\n if (getRenderer(renderer.name)) {\n throw new Error(\n `Renderer name \"${renderer.name}\" is already registered. Pick a different name or unregister the previous renderer first.`,\n );\n }\n extraRenderers.push(renderer);\n}\n\n/** @internal Reset the runtime registry between tests. */\nexport function clearRegisteredRenderersForTests(): void {\n extraRenderers.length = 0;\n}\n\n// Re-export the individual functions for backwards compatibility. They have\n// been the public API since v0.1.0 and consumers may import them directly.\n\nexport { renderMarkdown, renderDeltaMarkdown } from './markdown';\nexport { renderTerminal, renderDeltaTerminal } from './terminal';\nexport {\n renderJson,\n REPORT_SPEC,\n type JsonReport,\n type JsonReportEnvelope,\n} from './json';\nexport {\n EVENTCATALOG_SNAPSHOT_DIFF_SPEC,\n renderEventCatalogSnapshotDiffFromReport,\n renderEventCatalogSnapshotDiffFromDelta,\n type EventCatalogSnapshotDiffEnvelope,\n} from './eventcatalog-snapshot-diff';\nexport { type Renderer } from './types';\n","// Decide whether a drift outcome should fail a CI job.\n//\n// `policy` answers the gating question; it deliberately doesn't render or\n// print anything. `reason` carries a short, log-friendly explanation that\n// CLI / Action layers can surface in their exit messages.\n\nimport type { DriftDelta } from './diff-vs-base';\nimport type { DriftReport } from './diff';\nimport { hasDrift } from './diff';\n\nexport type DriftPolicyMode = 'all' | 'new-only';\n\nexport type PolicyEvaluationInput =\n | { mode: 'all'; report: DriftReport }\n | { mode: 'new-only'; delta: DriftDelta };\n\nexport type PolicyEvaluationResult = {\n shouldFail: boolean;\n reason: string;\n};\n\nexport function evaluatePolicy(\n input: PolicyEvaluationInput,\n): PolicyEvaluationResult {\n if (input.mode === 'all') {\n const shouldFail = hasDrift(input.report);\n return {\n shouldFail,\n reason: shouldFail\n ? 'Drift detected in current snapshot.'\n : 'No drift detected.',\n };\n }\n const shouldFail = input.delta.hasNewDrift;\n return {\n shouldFail,\n reason: shouldFail\n ? 'New drift introduced compared to baseline snapshot.'\n : 'No new drift introduced compared to baseline snapshot.',\n };\n}\n","// Stamp an architecture snapshot into a catalog's event mdx files.\n//\n// For each event in the snapshot that matches an event in the catalog (by\n// normalised name), the stamp command writes an evidence block between\n// `<!-- autotel:stamp-start -->` and `<!-- autotel:stamp-end -->` markers.\n// Subsequent runs replace the content between the markers idempotently, so\n// re-stamping is safe to run on every commit / in CI.\n//\n// If the markers do not yet exist in a file, they are inserted at the most\n// natural place: just before the `<Footer />` component if present, else\n// just before the closing `</...>` tag of the last visible content, else\n// appended to the file.\n\nimport { readFile, writeFile } from 'node:fs/promises';\nimport type { ArchitectureSnapshot, EventObservation } from './snapshot';\nimport { readCatalogState } from './catalog';\n\nexport const STAMP_START = '<!-- autotel:stamp-start -->';\nexport const STAMP_END = '<!-- autotel:stamp-end -->';\n\nexport interface StampOptions {\n /** Loaded snapshot, OR pass `loadSnapshot(path)` from the caller. */\n snapshot: ArchitectureSnapshot;\n /** Catalog root (the directory containing eventcatalog.config.*). */\n catalogPath: string;\n /** If true, do not write files; just return the diff plan. */\n dryRun?: boolean;\n /** Override \"now\" for deterministic tests. */\n now?: () => Date;\n}\n\nexport type StampUpdate = {\n /** Catalog event id, e.g. `OrderPlaced`. */\n catalogId: string;\n /** Snapshot event name, e.g. `order.placed`. */\n snapshotName: string;\n /** Absolute path to the mdx file that was (or would be) updated. */\n filePath: string;\n /** Was this an insert (no prior markers) or a replace? */\n action: 'insert' | 'replace';\n /**\n * True if the proposed content differs from what's on disk. False when a\n * replace would write byte-identical content; meaning no real change.\n * Used by `--summary-output` so CI can answer \"did this PR need stamping?\"\n * without diffing files.\n */\n changed: boolean;\n};\n\nexport type StampSkip = {\n snapshotName: string;\n reason: 'no-catalog-match';\n};\n\nexport type StampResult = {\n updates: StampUpdate[];\n skips: StampSkip[];\n};\n\nexport async function stampCatalog(opts: StampOptions): Promise<StampResult> {\n const { snapshot, catalogPath, dryRun = false } = opts;\n const catalog = await readCatalogState(catalogPath);\n\n const catalogByNormalised = new Map<\n string,\n { id: string; filePath: string }\n >();\n for (const [id, ev] of catalog.events) {\n catalogByNormalised.set(normaliseEventId(id), {\n id,\n filePath: ev.filePath,\n });\n }\n\n const updates: StampUpdate[] = [];\n const skips: StampSkip[] = [];\n\n for (const [name, obs] of Object.entries(snapshot.events)) {\n const match = catalogByNormalised.get(normaliseEventId(name));\n if (!match) {\n skips.push({ snapshotName: name, reason: 'no-catalog-match' });\n continue;\n }\n\n const block = buildStampBlock(obs);\n const { action, changed } = await stampFile(match.filePath, block, dryRun);\n\n updates.push({\n catalogId: match.id,\n snapshotName: name,\n filePath: match.filePath,\n action,\n changed,\n });\n }\n\n return { updates, skips };\n}\n\n/**\n * Render the evidence block. Designed to be readable in raw mdx AND visually\n * distinct when rendered by EventCatalog (uses the existing\n * `.evidence-callout` class, plus a small header label).\n */\nexport function buildStampBlock(obs: EventObservation): string {\n const lines: string[] = [\n STAMP_START,\n '',\n '<div class=\"evidence-callout\">',\n '<strong>Observed in autotel snapshot</strong>',\n '',\n ];\n const facts: string[] = [];\n facts.push(`**Volume**: ${obs.observedCount.toLocaleString()} events`);\n facts.push(`**Last seen**: ${formatTimestamp(obs.lastSeen)}`);\n if (obs.producer) facts.push(`**Producer**: ${obs.producer}`);\n if (obs.channel) facts.push(`**Channel**: \\`${obs.channel}\\``);\n lines.push(facts.join(' · '));\n if (obs.fieldPaths.length > 0) {\n lines.push('');\n lines.push(\n `**Field paths observed**: ${obs.fieldPaths.map((p) => `\\`${p}\\``).join(', ')}`,\n );\n }\n if (obs.sampleTraceIds.length > 0) {\n lines.push('');\n lines.push(\n `**Sample traces**: ${obs.sampleTraceIds.map((t) => `\\`${t}\\``).join(', ')}`,\n );\n }\n lines.push('</div>', '', STAMP_END);\n\n return lines.join('\\n');\n}\n\nasync function stampFile(\n filePath: string,\n block: string,\n dryRun: boolean,\n): Promise<{ action: 'insert' | 'replace'; changed: boolean }> {\n const content = await readFile(filePath, 'utf8');\n\n const startIdx = content.indexOf(STAMP_START);\n const endIdx = content.indexOf(STAMP_END);\n\n let next: string;\n let action: 'insert' | 'replace';\n\n if (startIdx !== -1 && endIdx > startIdx) {\n // Replace existing block (including markers).\n const before = content.slice(0, startIdx);\n const after = content.slice(endIdx + STAMP_END.length);\n next = before + block + after;\n action = 'replace';\n } else {\n // Insert. Prefer just before <Footer /> if present, else append.\n const footerIdx = content.search(/<Footer\\s*\\/>/);\n const insertion = '\\n\\n' + block + '\\n';\n next =\n footerIdx >= 0\n ? content.slice(0, footerIdx) +\n insertion +\n '\\n' +\n content.slice(footerIdx)\n : content.replace(/\\s*$/, '') + insertion;\n action = 'insert';\n }\n\n const changed = next !== content;\n if (!dryRun && changed) {\n await writeFile(filePath, next, 'utf8');\n }\n return { action, changed };\n}\n\n/** Versioned identifier for the stamp summary JSON file. */\nexport const STAMP_SUMMARY_SPEC =\n 'autotel-eventcatalog-stamp-summary/v0.1.0' as const;\n\nexport type StampSummary = {\n spec: typeof STAMP_SUMMARY_SPEC;\n dryRun: boolean;\n /** Total snapshot events the stamp run considered (matched + skipped). */\n attempted: number;\n /** Skipped events (no catalog match). */\n skipped: number;\n /** Matched events that resulted in an insert action. */\n inserts: number;\n /** Matched events that resulted in a replace action. */\n replaces: number;\n /** Number of files whose content actually changed (or would change in dry-run). */\n changedFiles: number;\n /**\n * True when the run produced (or would produce) any real change. CI can\n * gate on this: \"if the committed catalog is stamped, this should be\n * false after running stamp; if not, the PR forgot to re-stamp.\"\n */\n hadChanges: boolean;\n};\n\nexport function buildStampSummary(\n result: StampResult,\n dryRun: boolean,\n): StampSummary {\n const inserts = result.updates.filter((u) => u.action === 'insert').length;\n const replaces = result.updates.filter((u) => u.action === 'replace').length;\n const changedFiles = result.updates.filter((u) => u.changed).length;\n return {\n spec: STAMP_SUMMARY_SPEC,\n dryRun,\n attempted: result.updates.length + result.skips.length,\n skipped: result.skips.length,\n inserts,\n replaces,\n changedFiles,\n hadChanges: changedFiles > 0,\n };\n}\n\nfunction normaliseEventId(id: string): string {\n return id.toLowerCase().replaceAll(/[._\\-\\s]/g, '');\n}\n\nfunction formatTimestamp(iso: string): string {\n // 2026-05-22T05:23:50.024Z → 2026-05-22 05:23 UTC\n const d = new Date(iso);\n const pad = (n: number) => String(n).padStart(2, '0');\n return (\n `${d.getUTCFullYear()}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())} ` +\n `${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())} UTC`\n );\n}\n","import utils from '@eventcatalog/sdk';\nimport { readCatalogState } from './catalog';\nimport type { ArchitectureSnapshot, EventObservation } from './snapshot';\n\nexport interface GenerateOptions {\n snapshot: ArchitectureSnapshot;\n catalogPath: string;\n dryRun?: boolean;\n edgesOnly?: boolean;\n /** Version to assign to newly created resources. Defaults to '1.0.0'. */\n version?: string;\n}\n\nexport type GenerateSummaryItem = {\n kind: 'service' | 'event' | 'channel' | 'service-edge' | 'channel-edge';\n id: string;\n action: 'create' | 'exists' | 'link' | 'would-create' | 'would-link';\n detail?: string;\n /** For event items: where the JSON Schema came from. */\n schemaSource?: 'declared' | 'inferred';\n};\n\nexport interface GenerateResult {\n operations: GenerateSummaryItem[];\n}\n\nexport const GENERATE_SUMMARY_SPEC =\n 'autotel-eventcatalog-generate-summary/v0.1.0' as const;\n\nexport type GenerateSummary = {\n spec: typeof GENERATE_SUMMARY_SPEC;\n dryRun: boolean;\n edgesOnly: boolean;\n attempted: number;\n /** Top-level totals for dashboards / status checks. */\n totals: {\n created: number;\n linked: number;\n skipped: number;\n };\n /** Per-kind counts so consumers can render detail without re-deriving from `operations`. */\n created: {\n services: string[];\n events: string[];\n channels: string[];\n };\n edges: {\n sends: { service: string; event: string }[];\n receives: { service: string; event: string }[];\n messages: { channel: string; event: string }[];\n };\n /** Counts of declared- vs inferred-schema events created. Reveals adoption of `defineEvent`. */\n schemaSources: {\n declared: number;\n inferred: number;\n };\n skipped: {\n services: string[];\n events: string[];\n channels: string[];\n };\n};\n\ntype Sdk = ReturnType<typeof utils> & {\n writeService: (\n service: Record<string, unknown>,\n options?: Record<string, unknown>,\n ) => Promise<void>;\n writeEvent: (\n event: Record<string, unknown>,\n options?: Record<string, unknown>,\n ) => Promise<void>;\n writeChannel: (\n channel: Record<string, unknown>,\n options?: Record<string, unknown>,\n ) => Promise<void>;\n addSchemaToEvent: (\n id: string,\n schema: { schema: string; fileName: string },\n version?: string,\n ) => Promise<void>;\n addEventToService: (\n id: string,\n direction: 'sends' | 'receives',\n event: { id: string; version: string },\n version?: string,\n ) => Promise<void>;\n addEventToChannel: (\n id: string,\n event: { id: string; version: string; parameters?: Record<string, string> },\n version?: string,\n ) => Promise<void>;\n};\n\nconst DEFAULT_VERSION = '1.0.0';\n\nexport async function generateCatalogFromSnapshot(\n opts: GenerateOptions,\n): Promise<GenerateResult> {\n const {\n snapshot,\n catalogPath,\n dryRun = false,\n edgesOnly = false,\n version: resourceVersion = DEFAULT_VERSION,\n } = opts;\n const sdk = utils(catalogPath) as Sdk;\n const state = await readCatalogState(catalogPath);\n\n const operations: GenerateSummaryItem[] = [];\n\n const serviceIds = collectServices(snapshot);\n const channelIds = collectChannels(snapshot);\n\n const knownServices = new Set(state.services.keys());\n const knownChannels = new Set(state.channels.keys());\n const knownEvents = new Map<string, { id: string; version: string }>(\n [...state.events.entries()].map(([id, e]) => [\n normaliseEventId(id),\n { id, version: e.version ?? DEFAULT_VERSION },\n ]),\n );\n\n if (!edgesOnly) {\n for (const serviceId of serviceIds) {\n if (knownServices.has(serviceId)) {\n operations.push({ kind: 'service', id: serviceId, action: 'exists' });\n continue;\n }\n operations.push({\n kind: 'service',\n id: serviceId,\n action: dryRun ? 'would-create' : 'create',\n });\n if (!dryRun) {\n await sdk.writeService({\n id: serviceId,\n name: serviceId,\n version: resourceVersion,\n summary: `Generated from autotel snapshot (${snapshot.generatedAt})`,\n markdown: buildServiceMarkdown(serviceId, snapshot),\n });\n }\n knownServices.add(serviceId);\n }\n\n for (const channelId of channelIds) {\n if (knownChannels.has(channelId)) {\n operations.push({ kind: 'channel', id: channelId, action: 'exists' });\n continue;\n }\n operations.push({\n kind: 'channel',\n id: channelId,\n action: dryRun ? 'would-create' : 'create',\n });\n if (!dryRun) {\n await sdk.writeChannel({\n id: channelId,\n name: channelId,\n version: resourceVersion,\n summary: `Generated from autotel snapshot (${snapshot.generatedAt})`,\n address: channelId,\n protocols: ['kafka'],\n markdown: buildChannelMarkdown(channelId, snapshot),\n });\n }\n knownChannels.add(channelId);\n }\n\n for (const [snapshotName, obs] of Object.entries(snapshot.events)) {\n const normalised = normaliseEventId(snapshotName);\n const existing = knownEvents.get(normalised);\n if (existing) {\n operations.push({\n kind: 'event',\n id: existing.id,\n action: 'exists',\n detail: snapshotName,\n });\n continue;\n }\n\n const eventId = toCatalogEventId(snapshotName);\n const declared = obs.schema?.jsonSchema;\n const schema =\n (declared && typeof declared === 'object'\n ? (declared as Record<string, unknown>)\n : undefined) ?? inferJsonSchemaFromObservation(obs);\n const schemaSource = declared ? 'declared' : 'inferred';\n operations.push({\n kind: 'event',\n id: eventId,\n action: dryRun ? 'would-create' : 'create',\n detail: snapshotName,\n schemaSource,\n });\n if (!dryRun) {\n await sdk.writeEvent({\n id: eventId,\n name: eventId,\n version: resourceVersion,\n summary: `Generated from autotel snapshot event \"${snapshotName}\"`,\n schemaPath: 'schema.json',\n markdown: buildEventMarkdown(snapshotName, obs, schemaSource),\n // Bind to channel here rather than via sdk.addEventToChannel,\n // @eventcatalog/sdk@2.21.2 has a bug in addMessageToChannel where\n // the path split uses a string literal instead of a regex, which\n // ends up nesting a duplicate event file under index.mdx/. Setting\n // channels at write-time produces the same frontmatter and avoids\n // the corrupted layout.\n ...(obs.channel\n ? { channels: [{ id: obs.channel, version: DEFAULT_VERSION }] }\n : {}),\n });\n await sdk.addSchemaToEvent(eventId, {\n schema: JSON.stringify(schema, null, 2),\n fileName: 'schema.json',\n });\n }\n knownEvents.set(normalised, { id: eventId, version: resourceVersion });\n }\n }\n\n // Relationship generation: producer -> sends event\n for (const [snapshotName, obs] of Object.entries(snapshot.events)) {\n const event = knownEvents.get(normaliseEventId(snapshotName));\n if (!event) continue;\n if (obs.producer) {\n operations.push({\n kind: 'service-edge',\n id: `${obs.producer}->${event.id}`,\n action: dryRun ? 'would-link' : 'link',\n });\n if (!dryRun) {\n await sdk.addEventToService(obs.producer, 'sends', {\n id: event.id,\n version: event.version ?? resourceVersion,\n });\n }\n }\n for (const consumer of obs.consumers ?? []) {\n operations.push({\n kind: 'service-edge',\n id: `${consumer}<-${event.id}`,\n action: dryRun ? 'would-link' : 'link',\n detail: 'receives',\n });\n if (!dryRun) {\n await sdk.addEventToService(consumer, 'receives', {\n id: event.id,\n version: event.version ?? resourceVersion,\n });\n }\n }\n if (obs.channel) {\n operations.push({\n kind: 'channel-edge',\n id: `${event.id}->${obs.channel}`,\n action: dryRun ? 'would-link' : 'link',\n });\n // Channel edge is set on the event's `channels` frontmatter at\n // writeEvent time (see workaround note above). No SDK round-trip\n // needed here.\n }\n }\n\n return { operations };\n}\n\nexport function buildGenerateSummary(\n result: GenerateResult,\n options: { dryRun: boolean; edgesOnly: boolean },\n): GenerateSummary {\n const isCreate = (op: GenerateSummaryItem) =>\n op.action === 'create' || op.action === 'would-create';\n const isLink = (op: GenerateSummaryItem) =>\n op.action === 'link' || op.action === 'would-link';\n\n const created = {\n services: result.operations\n .filter((o) => o.kind === 'service' && isCreate(o))\n .map((o) => o.id),\n events: result.operations\n .filter((o) => o.kind === 'event' && isCreate(o))\n .map((o) => o.id),\n channels: result.operations\n .filter((o) => o.kind === 'channel' && isCreate(o))\n .map((o) => o.id),\n };\n\n const sends: { service: string; event: string }[] = [];\n const receives: { service: string; event: string }[] = [];\n const messages: { channel: string; event: string }[] = [];\n for (const op of result.operations) {\n if (!isLink(op)) continue;\n if (op.kind === 'service-edge') {\n if (op.detail === 'receives') {\n const [service, event] = op.id.split('<-');\n if (service && event) receives.push({ service, event });\n } else {\n const [service, event] = op.id.split('->');\n if (service && event) sends.push({ service, event });\n }\n } else if (op.kind === 'channel-edge') {\n const [event, channel] = op.id.split('->');\n if (event && channel) messages.push({ channel, event });\n }\n }\n\n const schemaSources = {\n declared: result.operations.filter(\n (o) => o.kind === 'event' && o.schemaSource === 'declared',\n ).length,\n inferred: result.operations.filter(\n (o) => o.kind === 'event' && o.schemaSource === 'inferred',\n ).length,\n };\n\n const skipped = {\n services: result.operations\n .filter((o) => o.kind === 'service' && o.action === 'exists')\n .map((o) => o.id),\n events: result.operations\n .filter((o) => o.kind === 'event' && o.action === 'exists')\n .map((o) => o.id),\n channels: result.operations\n .filter((o) => o.kind === 'channel' && o.action === 'exists')\n .map((o) => o.id),\n };\n\n const totalCreated =\n created.services.length + created.events.length + created.channels.length;\n const totalLinked = sends.length + receives.length + messages.length;\n const totalSkipped =\n skipped.services.length + skipped.events.length + skipped.channels.length;\n\n return {\n spec: GENERATE_SUMMARY_SPEC,\n dryRun: options.dryRun,\n edgesOnly: options.edgesOnly,\n attempted: result.operations.length,\n totals: {\n created: totalCreated,\n linked: totalLinked,\n skipped: totalSkipped,\n },\n created,\n edges: { sends, receives, messages },\n schemaSources,\n skipped,\n };\n}\n\nexport function inferJsonSchemaFromObservation(\n observation: EventObservation,\n): Record<string, unknown> {\n const root: Record<string, unknown> = {\n $schema: 'http://json-schema.org/draft-07/schema#',\n type: 'object',\n properties: {},\n };\n\n const paths = new Set<string>(observation.fieldPaths);\n for (const path of Object.keys(observation.fieldStats ?? {})) {\n paths.add(path);\n }\n\n const sorted = [...paths].toSorted();\n const stats = observation.fieldStats ?? {};\n for (const path of sorted) {\n insertSchemaPath(root, path, stats[path]?.types ?? []);\n }\n return root;\n}\n\nfunction insertSchemaPath(\n root: Record<string, unknown>,\n path: string,\n observedTypes: string[],\n): void {\n if (!path) return;\n const steps = parsePath(path);\n let current = root;\n\n for (let i = 0; i < steps.length; i++) {\n const step = steps[i];\n const last = i === steps.length - 1;\n\n if (!current.properties || typeof current.properties !== 'object') {\n current.properties = {};\n }\n const properties = current.properties as Record<string, unknown>;\n const next =\n (properties[step.key] as Record<string, unknown> | undefined) ?? {};\n properties[step.key] = next;\n\n if (step.array) {\n next.type = 'array';\n const items =\n (next.items as Record<string, unknown> | undefined) ??\n ({} as Record<string, unknown>);\n next.items = items;\n if (!last && (!items.type || items.type === 'array')) {\n items.type = 'object';\n }\n current = items;\n } else {\n if (last && observedTypes.length > 0) {\n setType(next, observedTypes);\n } else {\n if (!next.type || next.type === 'array') next.type = 'object';\n }\n current = next;\n }\n }\n}\n\nfunction setType(schemaNode: Record<string, unknown>, types: string[]): void {\n const mapped = mapRuntimeTypes(types);\n if (mapped.length === 1) {\n schemaNode.type = mapped[0];\n } else if (mapped.length > 1) {\n schemaNode.type = mapped;\n }\n}\n\nfunction mapRuntimeTypes(types: string[]): string[] {\n const out = new Set<string>();\n for (const t of types) {\n switch (t) {\n case 'string':\n case 'number':\n case 'boolean':\n case 'object':\n case 'array':\n case 'null':\n out.add(t);\n break;\n default:\n break;\n }\n }\n return [...out];\n}\n\nfunction parsePath(path: string): Array<{ key: string; array: boolean }> {\n const segments = path.split('.');\n const out: Array<{ key: string; array: boolean }> = [];\n for (const segment of segments) {\n const isArray = segment.endsWith('[]');\n out.push({\n key: isArray ? segment.slice(0, -2) : segment,\n array: isArray,\n });\n }\n return out;\n}\n\nfunction collectServices(snapshot: ArchitectureSnapshot): Set<string> {\n const out = new Set<string>();\n for (const obs of Object.values(snapshot.events)) {\n if (obs.producer) out.add(obs.producer);\n for (const consumer of obs.consumers ?? []) out.add(consumer);\n }\n return out;\n}\n\nfunction collectChannels(snapshot: ArchitectureSnapshot): Set<string> {\n const out = new Set<string>();\n for (const obs of Object.values(snapshot.events)) {\n if (obs.channel) out.add(obs.channel);\n }\n return out;\n}\n\nconst GENERATED_MARKER = '<!-- autotel:generated -->';\n\nconst GENERATED_PREAMBLE = `${GENERATED_MARKER}\n<!-- Edit freely. Subsequent \\`autotel-eventcatalog generate\\` runs skip files that already exist. -->`;\n\nfunction buildEventMarkdown(\n snapshotName: string,\n obs: EventObservation,\n schemaSource: 'declared' | 'inferred',\n): string {\n const traceLine = obs.sampleTraceIds[0]\n ? `- Sample trace: \\`${obs.sampleTraceIds[0]}\\`\\n`\n : '';\n const producerLine = obs.producer ? `- Producer: \\`${obs.producer}\\`\\n` : '';\n const channelLine = obs.channel ? `- Channel: \\`${obs.channel}\\`\\n` : '';\n const sourceLine =\n schemaSource === 'declared'\n ? '- Schema source: declared at the `track()` call site (Zod)'\n : '- Schema source: inferred from observed `fieldStats` (no declared schema at the call site yet)';\n\n return `${GENERATED_PREAMBLE}\n\n## ${snapshotName}\n\n*Generated from autotel snapshot. Add a human description, examples, and ownership.*\n\n### Evidence\n- Observed **${obs.observedCount}** time${obs.observedCount === 1 ? '' : 's'}\n- First seen: \\`${obs.firstSeen}\\`\n- Last seen: \\`${obs.lastSeen}\\`\n${producerLine}${channelLine}${traceLine}${sourceLine}\n`;\n}\n\nfunction buildServiceMarkdown(\n serviceId: string,\n snapshot: ArchitectureSnapshot,\n): string {\n const sends = Object.entries(snapshot.events)\n .filter(([, obs]) => obs.producer === serviceId)\n .map(([name]) => `- \\`${name}\\``)\n .join('\\n');\n const sendsBlock = sends ? `### Sends\\n${sends}\\n` : '';\n\n return `${GENERATED_PREAMBLE}\n\n## ${serviceId}\n\n*Generated from autotel snapshot. Add a human description and ownership.*\n\n${sendsBlock}`;\n}\n\nfunction buildChannelMarkdown(\n channelId: string,\n snapshot: ArchitectureSnapshot,\n): string {\n const messages = Object.entries(snapshot.events)\n .filter(([, obs]) => obs.channel === channelId)\n .map(([name]) => `- \\`${name}\\``)\n .join('\\n');\n const messagesBlock = messages ? `### Carries\\n${messages}\\n` : '';\n\n return `${GENERATED_PREAMBLE}\n\n## ${channelId}\n\n*Generated from autotel snapshot. Add transport details, retention, schema registry, etc.*\n\n${messagesBlock}`;\n}\n\nfunction toCatalogEventId(snapshotEventName: string): string {\n return snapshotEventName\n .split(/[._\\-\\s]+/)\n .filter(Boolean)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join('');\n}\n\nfunction normaliseEventId(id: string): string {\n return id.toLowerCase().replaceAll(/[._\\-\\s]/g, '');\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"generate-r5KccyNS.js","names":["normaliseEventId","collectChannels","normaliseEventId"],"sources":["../src/snapshot.ts","../src/catalog.ts","../src/diff.ts","../src/diff-vs-base.ts","../src/renderers/markdown.ts","../src/renderers/terminal.ts","../src/renderers/json.ts","../src/eventcatalog-snapshot-diff.ts","../src/renderers/eventcatalog-snapshot-diff.ts","../src/renderers/index.ts","../src/policy.ts","../src/stamp.ts","../src/generate.ts"],"sourcesContent":["// Re-export the snapshot types from autotel-subscribers and provide a\n// convenience loader. Keeping the types defined in one place makes the\n// contract between subscriber and generator unambiguous.\n\nimport { readFile } from 'node:fs/promises';\n\nexport type {\n ArchitectureSnapshot,\n EventObservation,\n} from 'autotel-subscribers/architecture-snapshot';\n\nimport type { ArchitectureSnapshot } from 'autotel-subscribers/architecture-snapshot';\n\nconst EXPECTED_SPEC_PREFIX = 'autotel-architecture/';\n\n/**\n * Loads and validates an autotel architecture snapshot from disk.\n *\n * Throws a descriptive error when the file is missing, contains invalid\n * JSON, or is not recognisable as an autotel snapshot, so the CLI surfaces\n * an actionable message rather than a raw `ENOENT` or `SyntaxError`.\n */\nexport async function loadSnapshot(\n path: string,\n): Promise<ArchitectureSnapshot> {\n let raw: string;\n try {\n raw = await readFile(path, 'utf8');\n } catch (err) {\n if (isNodeFsError(err) && err.code === 'ENOENT') {\n throw new Error(`Snapshot not found: ${path}`);\n }\n if (isNodeFsError(err) && err.code === 'EISDIR') {\n throw new Error(`Snapshot path is a directory, not a file: ${path}`);\n }\n throw new Error(\n `Could not read snapshot at ${path}: ${(err as Error).message}`,\n );\n }\n\n if (raw.trim().length === 0) {\n throw new Error(`Snapshot is empty: ${path}`);\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (err) {\n throw new Error(\n `Snapshot is not valid JSON: ${path} (${(err as Error).message})`,\n );\n }\n\n return validateSnapshot(parsed, path);\n}\n\n/**\n * Type guard that narrows `unknown` to `ArchitectureSnapshot` after checking\n * every required field. Replaces the previous `as ArchitectureSnapshot` cast\n * so the type story matches the runtime story: anything reaching the return\n * has been structurally verified.\n */\nfunction validateSnapshot(parsed: unknown, path: string): ArchitectureSnapshot {\n if (!isJsonObject(parsed)) {\n throw new Error(\n `Snapshot must be a JSON object: ${path} (got ${describe(parsed)})`,\n );\n }\n\n const { spec } = parsed;\n if (typeof spec !== 'string' || !spec.startsWith(EXPECTED_SPEC_PREFIX)) {\n const found =\n spec === undefined ? 'no `spec` field' : `spec=${describe(spec)}`;\n throw new Error(\n `Not an autotel architecture snapshot: ${path} (expected spec to start with \"${EXPECTED_SPEC_PREFIX}\", got ${found})`,\n );\n }\n\n // Order matters: the existing CLI surfaces \"missing events\" before\n // any other field-level errors, so users see the most useful diagnostic\n // first. The optional-required checks come after, only if events parsed.\n if (!isJsonObject(parsed.events)) {\n throw new Error(`Snapshot is missing required \\`events\\` map: ${path}`);\n }\n\n if (typeof parsed.service !== 'string' || parsed.service.length === 0) {\n throw new Error(`Snapshot is missing required \\`service\\` name: ${path}`);\n }\n\n if (typeof parsed.generatedAt !== 'string') {\n throw new Error(\n `Snapshot is missing required \\`generatedAt\\` (ISO 8601 string): ${path}`,\n );\n }\n\n for (const [name, observation] of Object.entries(parsed.events)) {\n if (!isJsonObject(observation)) {\n throw new Error(\n `Snapshot event \"${name}\" must be an object: ${path} (got ${describe(observation)})`,\n );\n }\n if (typeof observation.observedCount !== 'number') {\n throw new Error(\n `Snapshot event \"${name}\" is missing required \\`observedCount\\`: ${path}`,\n );\n }\n }\n\n return parsed as unknown as ArchitectureSnapshot;\n}\n\nfunction isJsonObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isNodeFsError(err: unknown): err is NodeJS.ErrnoException {\n return (\n err instanceof Error &&\n typeof (err as NodeJS.ErrnoException).code === 'string'\n );\n}\n\nfunction describe(value: unknown): string {\n if (value === null) return 'null';\n if (Array.isArray(value)) return 'array';\n return typeof value === 'string' ? JSON.stringify(value) : typeof value;\n}\n","// Read the current state of an EventCatalog using @eventcatalog/sdk. We\n// re-use SDK types (`Event`, `Service`, `Channel`) verbatim and only add the\n// two fields the SDK doesn't expose: the resolved on-disk `filePath`, and the\n// dotted field-path + schema-constraint extractions our drift diff consumes.\n// Inventing our own catalog types would silently drift from the SDK as it\n// evolves.\n\nimport utils from '@eventcatalog/sdk';\nimport type { Channel, Event, Service } from '@eventcatalog/sdk';\n\nexport type SchemaConstraint = {\n types?: string[];\n enumValues?: unknown[];\n};\n\nexport type CatalogEvent = Event & {\n /** Absolute path to the event's `index.mdx`, resolved via SDK. */\n filePath: string;\n /** Field paths declared in the event's JSON Schema (if present). */\n declaredFieldPaths?: string[];\n declaredSchemaConstraints?: Record<string, SchemaConstraint>;\n};\n\nexport type CatalogService = Service & {\n filePath: string;\n};\n\nexport type CatalogChannel = Channel & {\n filePath: string;\n};\n\nexport type CatalogState = {\n events: Map<string, CatalogEvent>;\n services: Map<string, CatalogService>;\n channels: Map<string, CatalogChannel>;\n};\n\nexport async function readCatalogState(\n catalogPath: string,\n): Promise<CatalogState> {\n const sdk = utils(catalogPath);\n\n const [events, services, channels] = await Promise.all([\n sdk.getEvents({ latestOnly: true, attachSchema: true }),\n sdk.getServices({ latestOnly: true }),\n sdk.getChannels({ latestOnly: true }),\n ]);\n\n const state: CatalogState = {\n events: new Map(),\n services: new Map(),\n channels: new Map(),\n };\n\n // SDK quirk (as of 2.21.2): unlike the other helpers, `getResourcePath` is\n // not curried with `catalogDir`, so we pass the catalog path explicitly.\n const resolveFilePath = async (id: string, version?: string) => {\n const paths = await sdk.getResourcePath(catalogPath, id, version);\n return paths?.fullPath ?? '';\n };\n\n for (const e of events ?? []) {\n const filePath = await resolveFilePath(e.id, e.version);\n const schemaExtractions = e.schema\n ? {\n declaredFieldPaths: extractDeclaredFieldPaths(e.schema),\n declaredSchemaConstraints: extractDeclaredSchemaConstraints(e.schema),\n }\n : {};\n state.events.set(e.id, { ...e, filePath, ...schemaExtractions });\n }\n\n for (const s of services ?? []) {\n const filePath = await resolveFilePath(s.id, s.version);\n state.services.set(s.id, { ...s, filePath });\n }\n\n for (const c of channels ?? []) {\n const filePath = await resolveFilePath(c.id, c.version);\n state.channels.set(c.id, { ...c, filePath });\n }\n\n return state;\n}\n\n/**\n * Extract field paths from a JSON Schema. Mirrors the dotted-path convention\n * used by the snapshot subscriber: arrays collapse to `[]`, nested objects\n * use `.`. We walk `properties` (objects) and `items` (arrays).\n */\nexport function extractDeclaredFieldPaths(\n schema: unknown,\n prefix = '',\n): string[] {\n const out = new Set<string>();\n walkSchema(schema, prefix, out);\n return [...out].toSorted();\n}\n\nfunction walkSchema(schema: unknown, prefix: string, out: Set<string>): void {\n if (!schema || typeof schema !== 'object') return;\n const s = schema as Record<string, unknown>;\n\n if (s.properties && typeof s.properties === 'object') {\n for (const [key, sub] of Object.entries(\n s.properties as Record<string, unknown>,\n )) {\n const path = prefix === '' ? key : `${prefix}.${key}`;\n out.add(path);\n walkSchema(sub, path, out);\n }\n }\n\n if (s.items) {\n const arrayPrefix = prefix + '[]';\n walkSchema(s.items, arrayPrefix, out);\n }\n}\n\nexport function extractDeclaredSchemaConstraints(\n schema: unknown,\n prefix = '',\n): Record<string, SchemaConstraint> {\n const out = new Map<string, SchemaConstraint>();\n walkSchemaConstraints(schema, prefix, out);\n const obj: Record<string, SchemaConstraint> = {};\n for (const [path, c] of out) obj[path] = c;\n return obj;\n}\n\nfunction walkSchemaConstraints(\n schema: unknown,\n prefix: string,\n out: Map<string, SchemaConstraint>,\n): void {\n if (!schema || typeof schema !== 'object') return;\n const s = schema as Record<string, unknown>;\n const typeVal = s.type;\n const enumVal = s.enum;\n if (prefix !== '' && (typeVal !== undefined || enumVal !== undefined)) {\n const types = toTypeArray(typeVal);\n const enumValues = Array.isArray(enumVal) ? [...enumVal] : undefined;\n out.set(prefix, {\n ...(types.length > 0 ? { types } : {}),\n ...(enumValues ? { enumValues } : {}),\n });\n }\n\n if (s.properties && typeof s.properties === 'object') {\n for (const [key, sub] of Object.entries(\n s.properties as Record<string, unknown>,\n )) {\n const path = prefix === '' ? key : `${prefix}.${key}`;\n walkSchemaConstraints(sub, path, out);\n }\n }\n if (s.items) {\n const arrayPrefix = prefix + '[]';\n walkSchemaConstraints(s.items, arrayPrefix, out);\n }\n}\n\nfunction toTypeArray(typeVal: unknown): string[] {\n if (typeof typeVal === 'string') return [typeVal];\n if (Array.isArray(typeVal)) {\n return typeVal.filter((t): t is string => typeof t === 'string').toSorted();\n }\n return [];\n}\n","// Compute drift between an autotel architecture snapshot and an existing\n// EventCatalog. The diff covers five drift classes:\n// - event existence (observedButUndocumented, documentedButUnseen)\n// - field-path drift (extras and missing per event)\n// - type drift (declared primitive type vs observed runtime types)\n// - value drift (declared enum vs observed sample values)\n// - service and channel existence drift\n\nimport type { ArchitectureSnapshot } from './snapshot';\nimport type { CatalogState } from './catalog';\n\nexport type EventDrift = {\n /** Event names observed in the snapshot but not present in the catalog. */\n observedButUndocumented: string[];\n /** Event names declared in the catalog but never observed in the snapshot. */\n documentedButUnseen: string[];\n /** Per-event field-path mismatches. */\n fieldDrift: FieldDrift[];\n /** Per-event field type mismatches against declared schema types. */\n typeDrift: TypeDrift[];\n /** Per-event enum/value mismatches against declared schema enums. */\n valueDrift: ValueDrift[];\n};\n\nexport type FieldDrift = {\n event: string;\n /** Field paths in the observed payload but not declared in the schema. */\n extra: string[];\n /** Field paths declared in the schema but never observed in a payload. */\n missing: string[];\n};\n\nexport type TypeDrift = {\n event: string;\n path: string;\n declared: string[];\n observed: string[];\n};\n\nexport type ValueDrift = {\n event: string;\n path: string;\n declared: unknown[];\n observed: unknown[];\n};\n\nexport type ServiceDrift = {\n /** Producers in the snapshot but not present in the catalog as services. */\n observedButUndocumented: string[];\n};\n\nexport type ChannelDrift = {\n /** Channels in the snapshot but not present in the catalog. */\n observedButUndocumented: string[];\n};\n\nexport type DriftReport = {\n snapshotGeneratedAt: string;\n snapshotService: string;\n events: EventDrift;\n services: ServiceDrift;\n channels: ChannelDrift;\n};\n\n/** True if the report contains any drift worth surfacing in a PR check. */\nexport function hasDrift(report: DriftReport): boolean {\n const c = countDriftReport(report);\n return c.total > 0;\n}\n\n/**\n * Per-category counts for a DriftReport. Keeps the dashboard's hero meter,\n * the CLI's summary-output, and the action's structured output all agreeing\n * on what \"N findings\" means.\n */\nexport type DriftCounts = {\n /** Total of all categories; what a dashboard \"drift findings\" badge shows. */\n total: number;\n observedButUndocumentedEvents: number;\n documentedButUnseenEvents: number;\n /** Number of distinct events with field-path drift entries. */\n fieldDriftEvents: number;\n /** Sum of every individual extra + missing path across all fieldDrift entries. */\n fieldDriftPaths: number;\n typeDriftPaths: number;\n valueDriftPaths: number;\n undocumentedServices: number;\n undocumentedChannels: number;\n};\n\nexport function countDriftReport(report: DriftReport): DriftCounts {\n const typeDrift = report.events.typeDrift ?? [];\n const valueDrift = report.events.valueDrift ?? [];\n const fieldDriftEvents = report.events.fieldDrift.length;\n const fieldDriftPaths = report.events.fieldDrift.reduce(\n (sum, fd) => sum + fd.extra.length + fd.missing.length,\n 0,\n );\n const typeDriftPaths = typeDrift.length;\n const valueDriftPaths = valueDrift.length;\n const observedButUndocumentedEvents =\n report.events.observedButUndocumented.length;\n const documentedButUnseenEvents = report.events.documentedButUnseen.length;\n const undocumentedServices = report.services.observedButUndocumented.length;\n const undocumentedChannels = report.channels.observedButUndocumented.length;\n\n return {\n observedButUndocumentedEvents,\n documentedButUnseenEvents,\n fieldDriftEvents,\n fieldDriftPaths,\n typeDriftPaths,\n valueDriftPaths,\n undocumentedServices,\n undocumentedChannels,\n total:\n observedButUndocumentedEvents +\n documentedButUnseenEvents +\n fieldDriftPaths +\n typeDriftPaths +\n valueDriftPaths +\n undocumentedServices +\n undocumentedChannels,\n };\n}\n\nexport function diffCatalogAgainstSnapshot(\n snapshot: ArchitectureSnapshot,\n catalog: CatalogState,\n): DriftReport {\n const snapshotEvents = new Set(Object.keys(snapshot.events));\n const catalogEventIds = new Set(catalog.events.keys());\n\n // Catalog event IDs are PascalCase (\"OrderPlaced\") while track() names are\n // dotted (\"order.placed\"). We compare on a normalised form so the same\n // event isn't reported as both missing and extra.\n const catalogEventByNormalised = new Map<string, string>();\n for (const id of catalogEventIds) {\n catalogEventByNormalised.set(normaliseEventId(id), id);\n }\n\n const observedButUndocumented: string[] = [];\n const matchedCatalogIds = new Set<string>();\n for (const name of snapshotEvents) {\n const matched = catalogEventByNormalised.get(normaliseEventId(name));\n if (matched) {\n matchedCatalogIds.add(matched);\n } else {\n observedButUndocumented.push(name);\n }\n }\n\n const documentedButUnseen: string[] = [];\n for (const id of catalogEventIds) {\n if (!matchedCatalogIds.has(id)) documentedButUnseen.push(id);\n }\n\n const fieldDrift: FieldDrift[] = [];\n const typeDrift: TypeDrift[] = [];\n const valueDrift: ValueDrift[] = [];\n for (const [snapName, obs] of Object.entries(snapshot.events)) {\n const catalogId = catalogEventByNormalised.get(normaliseEventId(snapName));\n if (!catalogId) continue;\n const eventDecl = catalog.events.get(catalogId);\n const declared = eventDecl?.declaredFieldPaths;\n if (!declared) continue;\n\n const declaredSet = new Set(declared);\n const observedSet = new Set(obs.fieldPaths);\n\n const extra = obs.fieldPaths.filter((p) => !declaredSet.has(p));\n const missing = declared.filter((p) => !observedSet.has(p));\n\n if (extra.length > 0 || missing.length > 0) {\n fieldDrift.push({ event: snapName, extra, missing });\n }\n\n const constraints = eventDecl?.declaredSchemaConstraints ?? {};\n const stats = obs.fieldStats ?? {};\n for (const [path, declaredConstraint] of Object.entries(constraints)) {\n const observed = stats[path];\n if (!observed) continue;\n if (declaredConstraint.types && declaredConstraint.types.length > 0) {\n // JSON Schema has `integer`; JavaScript has only `number`. Treat the\n // two as compatible at the runtime-type level, then use sample values\n // to flag the real signal (a non-integer value seen against an\n // integer-only declaration).\n const accepts = expandDeclaredTypes(declaredConstraint.types);\n const badTypes = observed.types.filter((t: string) => !accepts.has(t));\n const integerDeclared =\n declaredConstraint.types.includes('integer') &&\n !declaredConstraint.types.includes('number');\n const nonIntegerSamples = integerDeclared\n ? observed.sampleValues.filter(\n (v: unknown) => typeof v === 'number' && !Number.isInteger(v),\n )\n : [];\n if (badTypes.length > 0 || nonIntegerSamples.length > 0) {\n typeDrift.push({\n event: snapName,\n path,\n declared: declaredConstraint.types,\n observed: [...new Set(observed.types)].toSorted(),\n });\n }\n }\n if (\n declaredConstraint.enumValues &&\n declaredConstraint.enumValues.length > 0 &&\n observed.sampleValues.length > 0\n ) {\n const observedOutsideEnum = observed.sampleValues.filter(\n (v: unknown) =>\n !declaredConstraint.enumValues?.some((d) => Object.is(d, v)),\n );\n if (observedOutsideEnum.length > 0) {\n valueDrift.push({\n event: snapName,\n path,\n declared: declaredConstraint.enumValues,\n observed: [...new Set(observedOutsideEnum)] as unknown[],\n });\n }\n }\n }\n }\n\n const snapshotServices = collectProducers(snapshot);\n const catalogServiceIds = new Set(catalog.services.keys());\n const undocumentedServices = [...snapshotServices].filter(\n (id) => !catalogServiceIds.has(id),\n );\n\n const snapshotChannels = collectChannels(snapshot);\n const catalogChannelIds = new Set(catalog.channels.keys());\n const undocumentedChannels = [...snapshotChannels].filter(\n (id) => !catalogChannelIds.has(id),\n );\n\n return {\n snapshotGeneratedAt: snapshot.generatedAt,\n snapshotService: snapshot.service,\n events: {\n observedButUndocumented: observedButUndocumented.sort(),\n documentedButUnseen: documentedButUnseen.sort(),\n fieldDrift: fieldDrift.sort((a, b) => a.event.localeCompare(b.event)),\n typeDrift: typeDrift.sort((a, b) =>\n `${a.event}.${a.path}`.localeCompare(`${b.event}.${b.path}`),\n ),\n valueDrift: valueDrift.sort((a, b) =>\n `${a.event}.${a.path}`.localeCompare(`${b.event}.${b.path}`),\n ),\n },\n services: { observedButUndocumented: undocumentedServices.sort() },\n channels: { observedButUndocumented: undocumentedChannels.sort() },\n };\n}\n\n/**\n * Map declared JSON Schema types to the set of runtime types we accept at\n * `typeof` level. JSON Schema's `integer` is a refinement of `number` (JS\n * does not have a separate integer type), so we accept observed `number` for\n * either declaration. The integer-vs-fractional distinction is then enforced\n * separately against sample values.\n */\nfunction expandDeclaredTypes(declared: string[]): Set<string> {\n const accepts = new Set<string>(declared);\n if (declared.includes('integer')) accepts.add('number');\n return accepts;\n}\n\nfunction normaliseEventId(id: string): string {\n // \"order.placed\" -> \"orderplaced\", \"OrderPlaced\" -> \"orderplaced\".\n return id.toLowerCase().replaceAll(/[._\\-\\s]/g, '');\n}\n\nfunction collectProducers(snapshot: ArchitectureSnapshot): Set<string> {\n const out = new Set<string>();\n for (const obs of Object.values(snapshot.events)) {\n if (obs.producer) out.add(obs.producer);\n }\n return out;\n}\n\nfunction collectChannels(snapshot: ArchitectureSnapshot): Set<string> {\n const out = new Set<string>();\n for (const obs of Object.values(snapshot.events)) {\n if (obs.channel) out.add(obs.channel);\n }\n return out;\n}\n","// Compare two drift reports (base branch vs PR head) and produce a \"what\n// this PR introduces\" view. Without this, a PR check fails forever on\n// pre-existing drift; with it, the check only fails on drift the PR is\n// responsible for.\n\nimport type {\n DriftReport,\n FieldDrift,\n DriftCounts,\n TypeDrift,\n ValueDrift,\n} from './diff';\n\nexport type DriftDelta = {\n /** Drift entries present in head but not in base. */\n introduced: DriftEntries;\n /** Drift entries present in base but not in head; the PR fixed these. */\n resolved: DriftEntries;\n /** True if `introduced` has any non-empty section. */\n hasNewDrift: boolean;\n};\n\nexport type DriftEntries = {\n events: {\n observedButUndocumented: string[];\n documentedButUnseen: string[];\n fieldDrift: FieldDrift[];\n typeDrift: TypeDrift[];\n valueDrift: ValueDrift[];\n };\n services: { observedButUndocumented: string[] };\n channels: { observedButUndocumented: string[] };\n};\n\nexport function compareDriftReports(\n base: DriftReport,\n head: DriftReport,\n): DriftDelta {\n const introducedEvents = diffStringList(\n base.events.observedButUndocumented,\n head.events.observedButUndocumented,\n );\n const introducedMissing = diffStringList(\n base.events.documentedButUnseen,\n head.events.documentedButUnseen,\n );\n const introducedFieldDrift = diffFieldDrift(\n base.events.fieldDrift,\n head.events.fieldDrift,\n );\n const introducedServices = diffStringList(\n base.services.observedButUndocumented,\n head.services.observedButUndocumented,\n );\n const introducedChannels = diffStringList(\n base.channels.observedButUndocumented,\n head.channels.observedButUndocumented,\n );\n\n const introduced: DriftEntries = {\n events: {\n observedButUndocumented: introducedEvents.added,\n documentedButUnseen: introducedMissing.added,\n fieldDrift: introducedFieldDrift.added,\n typeDrift: diffTypeDrift(\n base.events.typeDrift ?? [],\n head.events.typeDrift ?? [],\n ).added,\n valueDrift: diffValueDrift(\n base.events.valueDrift ?? [],\n head.events.valueDrift ?? [],\n ).added,\n },\n services: { observedButUndocumented: introducedServices.added },\n channels: { observedButUndocumented: introducedChannels.added },\n };\n\n const resolved: DriftEntries = {\n events: {\n observedButUndocumented: introducedEvents.removed,\n documentedButUnseen: introducedMissing.removed,\n fieldDrift: introducedFieldDrift.removed,\n typeDrift: diffTypeDrift(\n base.events.typeDrift ?? [],\n head.events.typeDrift ?? [],\n ).removed,\n valueDrift: diffValueDrift(\n base.events.valueDrift ?? [],\n head.events.valueDrift ?? [],\n ).removed,\n },\n services: { observedButUndocumented: introducedServices.removed },\n channels: { observedButUndocumented: introducedChannels.removed },\n };\n\n const hasNewDrift =\n introduced.events.observedButUndocumented.length > 0 ||\n introduced.events.documentedButUnseen.length > 0 ||\n introduced.events.fieldDrift.length > 0 ||\n introduced.events.typeDrift.length > 0 ||\n introduced.events.valueDrift.length > 0 ||\n introduced.services.observedButUndocumented.length > 0 ||\n introduced.channels.observedButUndocumented.length > 0;\n\n return { introduced, resolved, hasNewDrift };\n}\n\n/**\n * Per-category counts for one side of a DriftDelta (introduced or resolved).\n * Same shape as DriftCounts so dashboards and CI can render the\n * introduced/resolved sections with identical accounting.\n */\nexport function countDriftEntries(entries: DriftEntries): DriftCounts {\n const fieldDriftEvents = entries.events.fieldDrift.length;\n const fieldDriftPaths = entries.events.fieldDrift.reduce(\n (sum, fd) => sum + fd.extra.length + fd.missing.length,\n 0,\n );\n const observedButUndocumentedEvents =\n entries.events.observedButUndocumented.length;\n const documentedButUnseenEvents = entries.events.documentedButUnseen.length;\n const undocumentedServices = entries.services.observedButUndocumented.length;\n const undocumentedChannels = entries.channels.observedButUndocumented.length;\n const typeDriftPaths = (entries.events.typeDrift ?? []).length;\n const valueDriftPaths = (entries.events.valueDrift ?? []).length;\n\n return {\n observedButUndocumentedEvents,\n documentedButUnseenEvents,\n fieldDriftEvents,\n fieldDriftPaths,\n typeDriftPaths,\n valueDriftPaths,\n undocumentedServices,\n undocumentedChannels,\n total:\n observedButUndocumentedEvents +\n documentedButUnseenEvents +\n fieldDriftPaths +\n typeDriftPaths +\n valueDriftPaths +\n undocumentedServices +\n undocumentedChannels,\n };\n}\n\nexport function countDriftDelta(delta: DriftDelta): {\n introduced: DriftCounts;\n resolved: DriftCounts;\n} {\n return {\n introduced: countDriftEntries(delta.introduced),\n resolved: countDriftEntries(delta.resolved),\n };\n}\n\nfunction diffStringList(\n base: string[],\n head: string[],\n): { added: string[]; removed: string[] } {\n const baseSet = new Set(base);\n const headSet = new Set(head);\n return {\n added: head.filter((s) => !baseSet.has(s)).sort(),\n removed: base.filter((s) => !headSet.has(s)).sort(),\n };\n}\n\nfunction diffFieldDrift(\n base: FieldDrift[],\n head: FieldDrift[],\n): { added: FieldDrift[]; removed: FieldDrift[] } {\n const baseByEvent = new Map(base.map((d) => [d.event, d]));\n const headByEvent = new Map(head.map((d) => [d.event, d]));\n\n const added: FieldDrift[] = [];\n const removed: FieldDrift[] = [];\n\n for (const [event, h] of headByEvent) {\n const b = baseByEvent.get(event);\n if (!b) {\n // Entire event's field drift is new to head.\n added.push(h);\n continue;\n }\n const addedExtra = h.extra.filter((p) => !b.extra.includes(p));\n const addedMissing = h.missing.filter((p) => !b.missing.includes(p));\n if (addedExtra.length > 0 || addedMissing.length > 0) {\n added.push({ event, extra: addedExtra, missing: addedMissing });\n }\n }\n\n for (const [event, b] of baseByEvent) {\n const h = headByEvent.get(event);\n if (!h) {\n removed.push(b);\n continue;\n }\n const removedExtra = b.extra.filter((p) => !h.extra.includes(p));\n const removedMissing = b.missing.filter((p) => !h.missing.includes(p));\n if (removedExtra.length > 0 || removedMissing.length > 0) {\n removed.push({ event, extra: removedExtra, missing: removedMissing });\n }\n }\n\n return { added, removed };\n}\n\nfunction diffTypeDrift(\n base: TypeDrift[],\n head: TypeDrift[],\n): { added: TypeDrift[]; removed: TypeDrift[] } {\n return diffStructuredByKey(base, head, (x) => `${x.event}::${x.path}`);\n}\n\nfunction diffValueDrift(\n base: ValueDrift[],\n head: ValueDrift[],\n): { added: ValueDrift[]; removed: ValueDrift[] } {\n return diffStructuredByKey(base, head, (x) => `${x.event}::${x.path}`);\n}\n\nfunction diffStructuredByKey<T>(\n base: T[],\n head: T[],\n keyOf: (v: T) => string,\n): { added: T[]; removed: T[] } {\n const baseMap = new Map(base.map((v) => [keyOf(v), v]));\n const headMap = new Map(head.map((v) => [keyOf(v), v]));\n const added: T[] = [];\n const removed: T[] = [];\n\n for (const [k, hv] of headMap) {\n const bv = baseMap.get(k);\n if (!bv || JSON.stringify(bv) !== JSON.stringify(hv)) added.push(hv);\n }\n for (const [k, bv] of baseMap) {\n const hv = headMap.get(k);\n if (!hv || JSON.stringify(hv) !== JSON.stringify(bv)) removed.push(bv);\n }\n return { added, removed };\n}\n","// GitHub-flavoured Markdown; the default. Used directly as the body of\n// the sticky PR comment posted by the bundled action.\n\nimport type { DriftReport, FieldDrift } from '../diff';\nimport { hasDrift } from '../diff';\nimport type { DriftDelta, DriftEntries } from '../diff-vs-base';\nimport type { Renderer } from './types';\n\nexport function renderMarkdown(report: DriftReport): string {\n const lines: string[] = [\n '# Architecture drift report',\n '',\n `_Snapshot from \\`${report.snapshotService}\\` at ${report.snapshotGeneratedAt}_`,\n '',\n ];\n\n if (!hasDrift(report)) {\n lines.push('No drift detected. Catalog and runtime agree.', '');\n return lines.join('\\n');\n }\n\n if (report.events.observedButUndocumented.length > 0) {\n lines.push(\n '## Events observed but undocumented',\n '',\n 'These event names appear in the snapshot but no matching entry',\n 'exists in the catalog. Add them or stop emitting them.',\n '',\n );\n for (const name of report.events.observedButUndocumented) {\n lines.push(`- \\`${name}\\``);\n }\n lines.push('');\n }\n\n if (report.events.documentedButUnseen.length > 0) {\n lines.push(\n '## Events documented but never observed',\n '',\n 'These events exist in the catalog but no payload was captured.',\n 'Either the tests do not exercise this event, or it has been removed.',\n '',\n );\n for (const name of report.events.documentedButUnseen) {\n lines.push(`- \\`${name}\\``);\n }\n lines.push('');\n }\n\n if (report.events.fieldDrift.length > 0) {\n lines.push('## Field-path drift', '');\n for (const drift of report.events.fieldDrift) {\n lines.push(`### \\`${drift.event}\\``, '');\n if (drift.extra.length > 0) {\n lines.push(\n '**Extra fields in payloads (not in declared schema):**',\n '',\n );\n for (const p of drift.extra) lines.push(`- \\`${p}\\``);\n lines.push('');\n }\n if (drift.missing.length > 0) {\n lines.push('**Fields declared but never observed:**', '');\n for (const p of drift.missing) lines.push(`- \\`${p}\\``);\n lines.push('');\n }\n }\n }\n\n if ((report.events.typeDrift ?? []).length > 0) {\n lines.push('## Type drift', '');\n for (const drift of report.events.typeDrift ?? []) {\n lines.push(\n `- \\`${drift.event}\\` \\`${drift.path}\\``,\n ` declared: \\`${drift.declared.join(' | ')}\\`, observed: \\`${drift.observed.join(' | ')}\\``,\n );\n }\n lines.push('');\n }\n\n if ((report.events.valueDrift ?? []).length > 0) {\n lines.push('## Value drift', '');\n for (const drift of report.events.valueDrift ?? []) {\n lines.push(\n `- \\`${drift.event}\\` \\`${drift.path}\\``,\n ` declared enum: \\`${drift.declared.map((v) => JSON.stringify(v)).join(', ')}\\`, observed: \\`${drift.observed.map((v) => JSON.stringify(v)).join(', ')}\\``,\n );\n }\n lines.push('');\n }\n\n if (report.services.observedButUndocumented.length > 0) {\n lines.push('## Services observed but undocumented', '');\n for (const id of report.services.observedButUndocumented) {\n lines.push(`- \\`${id}\\``);\n }\n lines.push('');\n }\n\n if (report.channels.observedButUndocumented.length > 0) {\n lines.push('## Channels observed but undocumented', '');\n for (const id of report.channels.observedButUndocumented) {\n lines.push(`- \\`${id}\\``);\n }\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Render the diff-of-diffs as a PR-comment-friendly markdown block. Sections\n * appear only when they have content, so a clean PR produces a tight message.\n */\nexport function renderDeltaMarkdown(delta: DriftDelta): string {\n const lines: string[] = [\n '# Architecture drift; what this change introduces',\n '',\n ];\n\n if (!delta.hasNewDrift) {\n const fixedAny = entriesHasContent(delta.resolved);\n if (fixedAny) {\n lines.push('No new drift. The changes below resolve existing drift:', '');\n renderEntries(delta.resolved, lines, { sign: '−' });\n } else {\n lines.push('No new drift detected. Catalog and runtime agree.');\n }\n lines.push('');\n return lines.join('\\n');\n }\n\n lines.push('This change introduces drift:', '');\n renderEntries(delta.introduced, lines, { sign: '+' });\n\n if (entriesHasContent(delta.resolved)) {\n lines.push('', '### Resolved by this change', '');\n renderEntries(delta.resolved, lines, { sign: '−' });\n }\n\n return lines.join('\\n');\n}\n\nfunction entriesHasContent(e: DriftEntries): boolean {\n return (\n e.events.observedButUndocumented.length > 0 ||\n e.events.documentedButUnseen.length > 0 ||\n e.events.fieldDrift.length > 0 ||\n (e.events.typeDrift ?? []).length > 0 ||\n (e.events.valueDrift ?? []).length > 0 ||\n e.services.observedButUndocumented.length > 0 ||\n e.channels.observedButUndocumented.length > 0\n );\n}\n\nfunction renderEntries(\n entries: DriftEntries,\n out: string[],\n options: { sign: '+' | '−' },\n): void {\n if (entries.events.observedButUndocumented.length > 0) {\n out.push('**Events observed but undocumented**', '');\n for (const n of entries.events.observedButUndocumented) {\n out.push(`- \\`${n}\\``);\n }\n out.push('');\n }\n if (entries.events.documentedButUnseen.length > 0) {\n out.push('**Events documented but never observed**', '');\n for (const n of entries.events.documentedButUnseen) {\n out.push(`- \\`${n}\\``);\n }\n out.push('');\n }\n for (const fd of entries.events.fieldDrift) {\n out.push(`**Field drift on \\`${fd.event}\\`**`, '');\n for (const p of fd.extra) out.push(`- ${options.sign} \\`${p}\\` (extra)`);\n for (const p of fd.missing)\n out.push(`- ${options.sign} \\`${p}\\` (missing)`);\n out.push('');\n }\n for (const td of entries.events.typeDrift ?? []) {\n out.push(\n `**Type drift on \\`${td.event}\\` \\`${td.path}\\`**`,\n '',\n `- ${options.sign} declared \\`${td.declared.join(' | ')}\\`, observed \\`${td.observed.join(' | ')}\\``,\n '',\n );\n }\n for (const vd of entries.events.valueDrift ?? []) {\n out.push(\n `**Value drift on \\`${vd.event}\\` \\`${vd.path}\\`**`,\n '',\n `- ${options.sign} declared enum \\`${vd.declared.map((v) => JSON.stringify(v)).join(', ')}\\`, observed \\`${vd.observed.map((v) => JSON.stringify(v)).join(', ')}\\``,\n '',\n );\n }\n if (entries.services.observedButUndocumented.length > 0) {\n out.push('**Services observed but undocumented**', '');\n for (const id of entries.services.observedButUndocumented) {\n out.push(`- \\`${id}\\``);\n }\n out.push('');\n }\n if (entries.channels.observedButUndocumented.length > 0) {\n out.push('**Channels observed but undocumented**', '');\n for (const id of entries.channels.observedButUndocumented) {\n out.push(`- \\`${id}\\``);\n }\n out.push('');\n }\n // FieldDrift import kept for typing of the for..of above; reference here so\n // the import isn't flagged as unused by some linter configurations.\n void (null as unknown as FieldDrift);\n}\n\nexport const markdownRenderer: Renderer = {\n name: 'markdown',\n description:\n 'GitHub-flavoured Markdown (default). Suitable for sticky PR comments.',\n renderReport: renderMarkdown,\n renderDelta: renderDeltaMarkdown,\n};\n","// Plain-text rendering; for terminals, log files, Slack messages, anywhere\n// markdown decorations would render as noise. Reuses the markdown renderer\n// and strips heading marks, inline code backticks, and bold emphasis.\n\nimport type { DriftReport } from '../diff';\nimport type { DriftDelta } from '../diff-vs-base';\nimport { renderMarkdown, renderDeltaMarkdown } from './markdown';\nimport type { Renderer } from './types';\n\nexport function renderTerminal(report: DriftReport): string {\n return stripMarkdownDecorations(renderMarkdown(report));\n}\n\nexport function renderDeltaTerminal(delta: DriftDelta): string {\n return stripMarkdownDecorations(renderDeltaMarkdown(delta));\n}\n\nfunction stripMarkdownDecorations(md: string): string {\n return md\n .replaceAll(/^#+\\s+/gm, '')\n .replaceAll('`', '')\n .replaceAll(/\\*\\*([^*]+)\\*\\*/g, '$1');\n}\n\nexport const terminalRenderer: Renderer = {\n name: 'terminal',\n description: 'Plain text. Same content as markdown, decorations stripped.',\n renderReport: renderTerminal,\n renderDelta: renderDeltaTerminal,\n};\n","// Versioned JSON envelope. Downstream tooling (dashboards, custom CI steps,\n// Slack bots) should read this rather than scraping the Markdown body. The\n// shape is governed by the published schema at\n// `schemas/drift-report-v0.2.0.json` and locked by golden contract tests.\n\nimport type { DriftReport } from '../diff';\nimport type { DriftDelta } from '../diff-vs-base';\nimport type { Renderer } from './types';\n\n/**\n * Versioned identifier baked into the JSON envelope. Bumping it is a\n * breaking change for downstream consumers; add fields rather than rename.\n */\nexport const REPORT_SPEC = 'autotel-eventcatalog-report/v0.2.0' as const;\n\nexport type JsonReport =\n | { mode: 'all'; report: DriftReport }\n | { mode: 'new-only'; delta: DriftDelta };\n\nexport type JsonReportEnvelope = { spec: typeof REPORT_SPEC } & JsonReport;\n\nexport function renderJson(data: JsonReport): string {\n const envelope: JsonReportEnvelope = { spec: REPORT_SPEC, ...data };\n return JSON.stringify(envelope, null, 2);\n}\n\nexport const jsonRenderer: Renderer = {\n name: 'json',\n description:\n 'Versioned JSON envelope. Validate against schemas/drift-report-v0.2.0.json.',\n renderReport: (report) => renderJson({ mode: 'all', report }),\n renderDelta: (delta) => renderJson({ mode: 'new-only', delta }),\n};\n","import type { DriftReport } from './diff';\nimport type { DriftDelta, DriftEntries } from './diff-vs-base';\n\nexport type SnapshotResourceType =\n 'event' | 'command' | 'query' | 'service' | 'domain' | 'channel';\n\nexport type ResourceChangeType = 'added' | 'removed' | 'modified' | 'versioned';\n\nexport type ResourceChange = {\n resourceId: string;\n version: string;\n type: SnapshotResourceType;\n changeType: ResourceChangeType;\n changedFields?: string[];\n previousVersion?: string;\n newVersion?: string;\n};\n\nexport type RelationshipChange = {\n serviceId: string;\n serviceVersion: string;\n resourceId: string;\n resourceVersion?: string;\n direction: 'sends' | 'receives';\n changeType: 'added' | 'removed';\n};\n\nexport type EventCatalogSnapshotDiff = {\n snapshotA: { label: string; createdAt: string };\n snapshotB: { label: string; createdAt: string };\n summary: {\n totalChanges: number;\n resourcesAdded: number;\n resourcesRemoved: number;\n resourcesModified: number;\n resourcesVersioned: number;\n relationshipsAdded: number;\n relationshipsRemoved: number;\n };\n resources: ResourceChange[];\n relationships: RelationshipChange[];\n};\n\nexport function toSnapshotDiffFromReport(\n report: DriftReport,\n): EventCatalogSnapshotDiff {\n const entries: DriftEntries = {\n events: report.events,\n services: report.services,\n channels: report.channels,\n };\n return snapshotDiffForEntries(entries, report.snapshotGeneratedAt, 'runtime');\n}\n\nexport function toSnapshotDiffFromDelta(\n delta: DriftDelta,\n): EventCatalogSnapshotDiff {\n return snapshotDiffForEntries(\n delta.introduced,\n new Date(0).toISOString(),\n 'runtime:new-drift',\n );\n}\n\nfunction snapshotDiffForEntries(\n entries: DriftEntries,\n createdAt: string,\n label: string,\n): EventCatalogSnapshotDiff {\n const resources: ResourceChange[] = [];\n const relationships: RelationshipChange[] = [];\n\n for (const eventName of entries.events.observedButUndocumented) {\n resources.push({\n resourceId: eventName,\n version: 'runtime',\n type: 'event',\n changeType: 'added',\n });\n }\n\n for (const eventName of entries.events.documentedButUnseen) {\n resources.push({\n resourceId: eventName,\n version: 'runtime',\n type: 'event',\n changeType: 'removed',\n });\n }\n\n for (const drift of entries.events.fieldDrift) {\n resources.push({\n resourceId: drift.event,\n version: 'runtime',\n type: 'event',\n changeType: 'modified',\n changedFields: [\n ...drift.extra.map((p) => `extra:${p}`),\n ...drift.missing.map((p) => `missing:${p}`),\n ],\n });\n }\n\n for (const drift of entries.events.typeDrift ?? []) {\n resources.push({\n resourceId: drift.event,\n version: 'runtime',\n type: 'event',\n changeType: 'modified',\n changedFields: [`type:${drift.path}`],\n });\n }\n\n for (const drift of entries.events.valueDrift ?? []) {\n resources.push({\n resourceId: drift.event,\n version: 'runtime',\n type: 'event',\n changeType: 'modified',\n changedFields: [`enum:${drift.path}`],\n });\n }\n\n for (const serviceId of entries.services.observedButUndocumented) {\n resources.push({\n resourceId: serviceId,\n version: 'runtime',\n type: 'service',\n changeType: 'added',\n });\n }\n\n for (const channelId of entries.channels.observedButUndocumented) {\n resources.push({\n resourceId: channelId,\n version: 'runtime',\n type: 'channel',\n changeType: 'added',\n });\n }\n\n const summary = {\n totalChanges: resources.length + relationships.length,\n resourcesAdded: resources.filter((r) => r.changeType === 'added').length,\n resourcesRemoved: resources.filter((r) => r.changeType === 'removed')\n .length,\n resourcesModified: resources.filter((r) => r.changeType === 'modified')\n .length,\n resourcesVersioned: resources.filter((r) => r.changeType === 'versioned')\n .length,\n relationshipsAdded: relationships.filter((r) => r.changeType === 'added')\n .length,\n relationshipsRemoved: relationships.filter(\n (r) => r.changeType === 'removed',\n ).length,\n };\n\n return {\n snapshotA: { label: 'catalog', createdAt: new Date(0).toISOString() },\n snapshotB: { label, createdAt },\n summary,\n resources,\n relationships,\n };\n}\n","import type { Renderer } from './types';\nimport type { DriftReport } from '../diff';\nimport type { DriftDelta } from '../diff-vs-base';\nimport {\n toSnapshotDiffFromDelta,\n toSnapshotDiffFromReport,\n} from '../eventcatalog-snapshot-diff';\n\nexport const EVENTCATALOG_SNAPSHOT_DIFF_SPEC =\n 'autotel-eventcatalog-snapshot-diff/v0.1.0' as const;\n\nexport type EventCatalogSnapshotDiffEnvelope = {\n spec: typeof EVENTCATALOG_SNAPSHOT_DIFF_SPEC;\n mode: 'all' | 'new-only';\n diff: ReturnType<typeof toSnapshotDiffFromReport>;\n};\n\nexport function renderEventCatalogSnapshotDiffFromReport(\n report: DriftReport,\n): string {\n const envelope: EventCatalogSnapshotDiffEnvelope = {\n spec: EVENTCATALOG_SNAPSHOT_DIFF_SPEC,\n mode: 'all',\n diff: toSnapshotDiffFromReport(report),\n };\n return JSON.stringify(envelope, null, 2);\n}\n\nexport function renderEventCatalogSnapshotDiffFromDelta(\n delta: DriftDelta,\n): string {\n const envelope: EventCatalogSnapshotDiffEnvelope = {\n spec: EVENTCATALOG_SNAPSHOT_DIFF_SPEC,\n mode: 'new-only',\n diff: toSnapshotDiffFromDelta(delta),\n };\n return JSON.stringify(envelope, null, 2);\n}\n\nexport const eventcatalogSnapshotDiffRenderer: Renderer = {\n name: 'eventcatalog-snapshot-diff',\n description:\n 'EventCatalog SnapshotDiff-compatible JSON for catalog-native drift views.',\n renderReport: renderEventCatalogSnapshotDiffFromReport,\n renderDelta: renderEventCatalogSnapshotDiffFromDelta,\n};\n","// Registry of available renderers. The CLI dispatches `--format <name>`\n// through here; future renderers (sarif, slack, github-check-runs) drop in\n// by adding an entry to `RENDERERS`.\n\nimport type { Renderer } from './types';\nimport { markdownRenderer } from './markdown';\nimport { terminalRenderer } from './terminal';\nimport { jsonRenderer } from './json';\nimport { eventcatalogSnapshotDiffRenderer } from './eventcatalog-snapshot-diff';\n\nconst BUILTIN_RENDERERS: readonly Renderer[] = [\n markdownRenderer,\n terminalRenderer,\n jsonRenderer,\n eventcatalogSnapshotDiffRenderer,\n];\n\nconst extraRenderers: Renderer[] = [];\n\n/**\n * @deprecated Use `listRenderers()` for the full registry (built-ins plus\n * any registered at runtime). Kept for backwards compatibility.\n */\nexport const RENDERERS: readonly Renderer[] = BUILTIN_RENDERERS;\n\n/**\n * Names of the built-in renderers, narrowed to a string literal union via\n * `as const`. Custom renderers registered via `registerRenderer` widen the\n * runtime set but not this type; the CLI uses `listRendererNames()` for\n * runtime listings.\n */\nexport const RENDERER_NAMES = [\n 'markdown',\n 'terminal',\n 'json',\n 'eventcatalog-snapshot-diff',\n] as const;\n\nexport type RendererName = (typeof RENDERER_NAMES)[number];\n\nexport function getRenderer(name: string): Renderer | undefined {\n return listRenderers().find((r) => r.name === name);\n}\n\nexport function listRenderers(): readonly Renderer[] {\n return [...BUILTIN_RENDERERS, ...extraRenderers];\n}\n\nexport function listRendererNames(): readonly string[] {\n return listRenderers().map((r) => r.name);\n}\n\n/**\n * Register a custom renderer at runtime. The CLI calls this when a\n * `--register-renderer <module>` flag is supplied; library users may call\n * it directly before invoking `runDrift`/`runStamp`/`runGenerate`.\n */\nexport function registerRenderer(renderer: Renderer): void {\n if (getRenderer(renderer.name)) {\n throw new Error(\n `Renderer name \"${renderer.name}\" is already registered. Pick a different name or unregister the previous renderer first.`,\n );\n }\n extraRenderers.push(renderer);\n}\n\n/** @internal Reset the runtime registry between tests. */\nexport function clearRegisteredRenderersForTests(): void {\n extraRenderers.length = 0;\n}\n\n// Re-export the individual functions for backwards compatibility. They have\n// been the public API since v0.1.0 and consumers may import them directly.\n\nexport { renderMarkdown, renderDeltaMarkdown } from './markdown';\nexport { renderTerminal, renderDeltaTerminal } from './terminal';\nexport {\n renderJson,\n REPORT_SPEC,\n type JsonReport,\n type JsonReportEnvelope,\n} from './json';\nexport {\n EVENTCATALOG_SNAPSHOT_DIFF_SPEC,\n renderEventCatalogSnapshotDiffFromReport,\n renderEventCatalogSnapshotDiffFromDelta,\n type EventCatalogSnapshotDiffEnvelope,\n} from './eventcatalog-snapshot-diff';\nexport { type Renderer } from './types';\n","// Decide whether a drift outcome should fail a CI job.\n//\n// `policy` answers the gating question; it deliberately doesn't render or\n// print anything. `reason` carries a short, log-friendly explanation that\n// CLI / Action layers can surface in their exit messages.\n\nimport type { DriftDelta } from './diff-vs-base';\nimport type { DriftReport } from './diff';\nimport { hasDrift } from './diff';\n\nexport type DriftPolicyMode = 'all' | 'new-only';\n\nexport type PolicyEvaluationInput =\n | { mode: 'all'; report: DriftReport }\n | { mode: 'new-only'; delta: DriftDelta };\n\nexport type PolicyEvaluationResult = {\n shouldFail: boolean;\n reason: string;\n};\n\nexport function evaluatePolicy(\n input: PolicyEvaluationInput,\n): PolicyEvaluationResult {\n if (input.mode === 'all') {\n const shouldFail = hasDrift(input.report);\n return {\n shouldFail,\n reason: shouldFail\n ? 'Drift detected in current snapshot.'\n : 'No drift detected.',\n };\n }\n const shouldFail = input.delta.hasNewDrift;\n return {\n shouldFail,\n reason: shouldFail\n ? 'New drift introduced compared to baseline snapshot.'\n : 'No new drift introduced compared to baseline snapshot.',\n };\n}\n","// Stamp an architecture snapshot into a catalog's event mdx files.\n//\n// For each event in the snapshot that matches an event in the catalog (by\n// normalised name), the stamp command writes an evidence block between\n// `<!-- autotel:stamp-start -->` and `<!-- autotel:stamp-end -->` markers.\n// Subsequent runs replace the content between the markers idempotently, so\n// re-stamping is safe to run on every commit / in CI.\n//\n// If the markers do not yet exist in a file, they are inserted at the most\n// natural place: just before the `<Footer />` component if present, else\n// just before the closing `</...>` tag of the last visible content, else\n// appended to the file.\n\nimport { readFile, writeFile } from 'node:fs/promises';\nimport type { ArchitectureSnapshot, EventObservation } from './snapshot';\nimport { readCatalogState } from './catalog';\n\nexport const STAMP_START = '<!-- autotel:stamp-start -->';\nexport const STAMP_END = '<!-- autotel:stamp-end -->';\n\nexport interface StampOptions {\n /** Loaded snapshot, OR pass `loadSnapshot(path)` from the caller. */\n snapshot: ArchitectureSnapshot;\n /** Catalog root (the directory containing eventcatalog.config.*). */\n catalogPath: string;\n /** If true, do not write files; just return the diff plan. */\n dryRun?: boolean;\n /** Override \"now\" for deterministic tests. */\n now?: () => Date;\n}\n\nexport type StampUpdate = {\n /** Catalog event id, e.g. `OrderPlaced`. */\n catalogId: string;\n /** Snapshot event name, e.g. `order.placed`. */\n snapshotName: string;\n /** Absolute path to the mdx file that was (or would be) updated. */\n filePath: string;\n /** Was this an insert (no prior markers) or a replace? */\n action: 'insert' | 'replace';\n /**\n * True if the proposed content differs from what's on disk. False when a\n * replace would write byte-identical content; meaning no real change.\n * Used by `--summary-output` so CI can answer \"did this PR need stamping?\"\n * without diffing files.\n */\n changed: boolean;\n};\n\nexport type StampSkip = {\n snapshotName: string;\n reason: 'no-catalog-match';\n};\n\nexport type StampResult = {\n updates: StampUpdate[];\n skips: StampSkip[];\n};\n\nexport async function stampCatalog(opts: StampOptions): Promise<StampResult> {\n const { snapshot, catalogPath, dryRun = false } = opts;\n const catalog = await readCatalogState(catalogPath);\n\n const catalogByNormalised = new Map<\n string,\n { id: string; filePath: string }\n >();\n for (const [id, ev] of catalog.events) {\n catalogByNormalised.set(normaliseEventId(id), {\n id,\n filePath: ev.filePath,\n });\n }\n\n const updates: StampUpdate[] = [];\n const skips: StampSkip[] = [];\n\n for (const [name, obs] of Object.entries(snapshot.events)) {\n const match = catalogByNormalised.get(normaliseEventId(name));\n if (!match) {\n skips.push({ snapshotName: name, reason: 'no-catalog-match' });\n continue;\n }\n\n const block = buildStampBlock(obs);\n const { action, changed } = await stampFile(match.filePath, block, dryRun);\n\n updates.push({\n catalogId: match.id,\n snapshotName: name,\n filePath: match.filePath,\n action,\n changed,\n });\n }\n\n return { updates, skips };\n}\n\n/**\n * Render the evidence block. Designed to be readable in raw mdx AND visually\n * distinct when rendered by EventCatalog (uses the existing\n * `.evidence-callout` class, plus a small header label).\n */\nexport function buildStampBlock(obs: EventObservation): string {\n const lines: string[] = [\n STAMP_START,\n '',\n '<div class=\"evidence-callout\">',\n '<strong>Observed in autotel snapshot</strong>',\n '',\n ];\n const facts: string[] = [];\n facts.push(`**Volume**: ${obs.observedCount.toLocaleString()} events`);\n facts.push(`**Last seen**: ${formatTimestamp(obs.lastSeen)}`);\n if (obs.producer) facts.push(`**Producer**: ${obs.producer}`);\n if (obs.channel) facts.push(`**Channel**: \\`${obs.channel}\\``);\n lines.push(facts.join(' · '));\n if (obs.fieldPaths.length > 0) {\n lines.push('');\n lines.push(\n `**Field paths observed**: ${obs.fieldPaths.map((p) => `\\`${p}\\``).join(', ')}`,\n );\n }\n if (obs.sampleTraceIds.length > 0) {\n lines.push('');\n lines.push(\n `**Sample traces**: ${obs.sampleTraceIds.map((t) => `\\`${t}\\``).join(', ')}`,\n );\n }\n lines.push('</div>', '', STAMP_END);\n\n return lines.join('\\n');\n}\n\nasync function stampFile(\n filePath: string,\n block: string,\n dryRun: boolean,\n): Promise<{ action: 'insert' | 'replace'; changed: boolean }> {\n const content = await readFile(filePath, 'utf8');\n\n const startIdx = content.indexOf(STAMP_START);\n const endIdx = content.indexOf(STAMP_END);\n\n let next: string;\n let action: 'insert' | 'replace';\n\n if (startIdx !== -1 && endIdx > startIdx) {\n // Replace existing block (including markers).\n const before = content.slice(0, startIdx);\n const after = content.slice(endIdx + STAMP_END.length);\n next = before + block + after;\n action = 'replace';\n } else {\n // Insert. Prefer just before <Footer /> if present, else append.\n const footerIdx = content.search(/<Footer\\s*\\/>/);\n const insertion = '\\n\\n' + block + '\\n';\n next =\n footerIdx >= 0\n ? content.slice(0, footerIdx) +\n insertion +\n '\\n' +\n content.slice(footerIdx)\n : content.replace(/\\s*$/, '') + insertion;\n action = 'insert';\n }\n\n const changed = next !== content;\n if (!dryRun && changed) {\n await writeFile(filePath, next, 'utf8');\n }\n return { action, changed };\n}\n\n/** Versioned identifier for the stamp summary JSON file. */\nexport const STAMP_SUMMARY_SPEC =\n 'autotel-eventcatalog-stamp-summary/v0.1.0' as const;\n\nexport type StampSummary = {\n spec: typeof STAMP_SUMMARY_SPEC;\n dryRun: boolean;\n /** Total snapshot events the stamp run considered (matched + skipped). */\n attempted: number;\n /** Skipped events (no catalog match). */\n skipped: number;\n /** Matched events that resulted in an insert action. */\n inserts: number;\n /** Matched events that resulted in a replace action. */\n replaces: number;\n /** Number of files whose content actually changed (or would change in dry-run). */\n changedFiles: number;\n /**\n * True when the run produced (or would produce) any real change. CI can\n * gate on this: \"if the committed catalog is stamped, this should be\n * false after running stamp; if not, the PR forgot to re-stamp.\"\n */\n hadChanges: boolean;\n};\n\nexport function buildStampSummary(\n result: StampResult,\n dryRun: boolean,\n): StampSummary {\n const inserts = result.updates.filter((u) => u.action === 'insert').length;\n const replaces = result.updates.filter((u) => u.action === 'replace').length;\n const changedFiles = result.updates.filter((u) => u.changed).length;\n return {\n spec: STAMP_SUMMARY_SPEC,\n dryRun,\n attempted: result.updates.length + result.skips.length,\n skipped: result.skips.length,\n inserts,\n replaces,\n changedFiles,\n hadChanges: changedFiles > 0,\n };\n}\n\nfunction normaliseEventId(id: string): string {\n return id.toLowerCase().replaceAll(/[._\\-\\s]/g, '');\n}\n\nfunction formatTimestamp(iso: string): string {\n // 2026-05-22T05:23:50.024Z → 2026-05-22 05:23 UTC\n const d = new Date(iso);\n const pad = (n: number) => String(n).padStart(2, '0');\n return (\n `${d.getUTCFullYear()}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())} ` +\n `${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())} UTC`\n );\n}\n","import utils from '@eventcatalog/sdk';\nimport { readCatalogState } from './catalog';\nimport type { ArchitectureSnapshot, EventObservation } from './snapshot';\n\nexport interface GenerateOptions {\n snapshot: ArchitectureSnapshot;\n catalogPath: string;\n dryRun?: boolean;\n edgesOnly?: boolean;\n /** Version to assign to newly created resources. Defaults to '1.0.0'. */\n version?: string;\n}\n\nexport type GenerateSummaryItem = {\n kind: 'service' | 'event' | 'channel' | 'service-edge' | 'channel-edge';\n id: string;\n action: 'create' | 'exists' | 'link' | 'would-create' | 'would-link';\n detail?: string;\n /** For event items: where the JSON Schema came from. */\n schemaSource?: 'declared' | 'inferred';\n};\n\nexport interface GenerateResult {\n operations: GenerateSummaryItem[];\n}\n\nexport const GENERATE_SUMMARY_SPEC =\n 'autotel-eventcatalog-generate-summary/v0.1.0' as const;\n\nexport type GenerateSummary = {\n spec: typeof GENERATE_SUMMARY_SPEC;\n dryRun: boolean;\n edgesOnly: boolean;\n attempted: number;\n /** Top-level totals for dashboards / status checks. */\n totals: {\n created: number;\n linked: number;\n skipped: number;\n };\n /** Per-kind counts so consumers can render detail without re-deriving from `operations`. */\n created: {\n services: string[];\n events: string[];\n channels: string[];\n };\n edges: {\n sends: { service: string; event: string }[];\n receives: { service: string; event: string }[];\n messages: { channel: string; event: string }[];\n };\n /** Counts of declared- vs inferred-schema events created. Reveals adoption of `defineEvent`. */\n schemaSources: {\n declared: number;\n inferred: number;\n };\n skipped: {\n services: string[];\n events: string[];\n channels: string[];\n };\n};\n\ntype Sdk = ReturnType<typeof utils> & {\n writeService: (\n service: Record<string, unknown>,\n options?: Record<string, unknown>,\n ) => Promise<void>;\n writeEvent: (\n event: Record<string, unknown>,\n options?: Record<string, unknown>,\n ) => Promise<void>;\n writeChannel: (\n channel: Record<string, unknown>,\n options?: Record<string, unknown>,\n ) => Promise<void>;\n addSchemaToEvent: (\n id: string,\n schema: { schema: string; fileName: string },\n version?: string,\n ) => Promise<void>;\n addEventToService: (\n id: string,\n direction: 'sends' | 'receives',\n event: { id: string; version: string },\n version?: string,\n ) => Promise<void>;\n addEventToChannel: (\n id: string,\n event: { id: string; version: string; parameters?: Record<string, string> },\n version?: string,\n ) => Promise<void>;\n};\n\nconst DEFAULT_VERSION = '1.0.0';\n\nexport async function generateCatalogFromSnapshot(\n opts: GenerateOptions,\n): Promise<GenerateResult> {\n const {\n snapshot,\n catalogPath,\n dryRun = false,\n edgesOnly = false,\n version: resourceVersion = DEFAULT_VERSION,\n } = opts;\n const sdk = utils(catalogPath) as Sdk;\n const state = await readCatalogState(catalogPath);\n\n const operations: GenerateSummaryItem[] = [];\n\n const serviceIds = collectServices(snapshot);\n const channelIds = collectChannels(snapshot);\n\n const knownServices = new Set(state.services.keys());\n const knownChannels = new Set(state.channels.keys());\n const knownEvents = new Map<string, { id: string; version: string }>(\n [...state.events.entries()].map(([id, e]) => [\n normaliseEventId(id),\n { id, version: e.version ?? DEFAULT_VERSION },\n ]),\n );\n\n if (!edgesOnly) {\n for (const serviceId of serviceIds) {\n if (knownServices.has(serviceId)) {\n operations.push({ kind: 'service', id: serviceId, action: 'exists' });\n continue;\n }\n operations.push({\n kind: 'service',\n id: serviceId,\n action: dryRun ? 'would-create' : 'create',\n });\n if (!dryRun) {\n await sdk.writeService({\n id: serviceId,\n name: serviceId,\n version: resourceVersion,\n summary: `Generated from autotel snapshot (${snapshot.generatedAt})`,\n markdown: buildServiceMarkdown(serviceId, snapshot),\n });\n }\n knownServices.add(serviceId);\n }\n\n for (const channelId of channelIds) {\n if (knownChannels.has(channelId)) {\n operations.push({ kind: 'channel', id: channelId, action: 'exists' });\n continue;\n }\n operations.push({\n kind: 'channel',\n id: channelId,\n action: dryRun ? 'would-create' : 'create',\n });\n if (!dryRun) {\n await sdk.writeChannel({\n id: channelId,\n name: channelId,\n version: resourceVersion,\n summary: `Generated from autotel snapshot (${snapshot.generatedAt})`,\n address: channelId,\n protocols: ['kafka'],\n markdown: buildChannelMarkdown(channelId, snapshot),\n });\n }\n knownChannels.add(channelId);\n }\n\n for (const [snapshotName, obs] of Object.entries(snapshot.events)) {\n const normalised = normaliseEventId(snapshotName);\n const existing = knownEvents.get(normalised);\n if (existing) {\n operations.push({\n kind: 'event',\n id: existing.id,\n action: 'exists',\n detail: snapshotName,\n });\n continue;\n }\n\n const eventId = toCatalogEventId(snapshotName);\n const declared = obs.schema?.jsonSchema;\n const schema =\n (declared && typeof declared === 'object'\n ? (declared as Record<string, unknown>)\n : undefined) ?? inferJsonSchemaFromObservation(obs);\n const schemaSource = declared ? 'declared' : 'inferred';\n operations.push({\n kind: 'event',\n id: eventId,\n action: dryRun ? 'would-create' : 'create',\n detail: snapshotName,\n schemaSource,\n });\n if (!dryRun) {\n await sdk.writeEvent({\n id: eventId,\n name: eventId,\n version: resourceVersion,\n summary: `Generated from autotel snapshot event \"${snapshotName}\"`,\n schemaPath: 'schema.json',\n markdown: buildEventMarkdown(snapshotName, obs, schemaSource),\n // Bind to channel here rather than via sdk.addEventToChannel,\n // @eventcatalog/sdk@2.21.2 has a bug in addMessageToChannel where\n // the path split uses a string literal instead of a regex, which\n // ends up nesting a duplicate event file under index.mdx/. Setting\n // channels at write-time produces the same frontmatter and avoids\n // the corrupted layout.\n ...(obs.channel\n ? { channels: [{ id: obs.channel, version: DEFAULT_VERSION }] }\n : {}),\n });\n await sdk.addSchemaToEvent(eventId, {\n schema: JSON.stringify(schema, null, 2),\n fileName: 'schema.json',\n });\n }\n knownEvents.set(normalised, { id: eventId, version: resourceVersion });\n }\n }\n\n // Relationship generation: producer -> sends event\n for (const [snapshotName, obs] of Object.entries(snapshot.events)) {\n const event = knownEvents.get(normaliseEventId(snapshotName));\n if (!event) continue;\n if (obs.producer) {\n operations.push({\n kind: 'service-edge',\n id: `${obs.producer}->${event.id}`,\n action: dryRun ? 'would-link' : 'link',\n });\n if (!dryRun) {\n await sdk.addEventToService(obs.producer, 'sends', {\n id: event.id,\n version: event.version ?? resourceVersion,\n });\n }\n }\n for (const consumer of obs.consumers ?? []) {\n operations.push({\n kind: 'service-edge',\n id: `${consumer}<-${event.id}`,\n action: dryRun ? 'would-link' : 'link',\n detail: 'receives',\n });\n if (!dryRun) {\n await sdk.addEventToService(consumer, 'receives', {\n id: event.id,\n version: event.version ?? resourceVersion,\n });\n }\n }\n if (obs.channel) {\n operations.push({\n kind: 'channel-edge',\n id: `${event.id}->${obs.channel}`,\n action: dryRun ? 'would-link' : 'link',\n });\n // Channel edge is set on the event's `channels` frontmatter at\n // writeEvent time (see workaround note above). No SDK round-trip\n // needed here.\n }\n }\n\n return { operations };\n}\n\nexport function buildGenerateSummary(\n result: GenerateResult,\n options: { dryRun: boolean; edgesOnly: boolean },\n): GenerateSummary {\n const isCreate = (op: GenerateSummaryItem) =>\n op.action === 'create' || op.action === 'would-create';\n const isLink = (op: GenerateSummaryItem) =>\n op.action === 'link' || op.action === 'would-link';\n\n const created = {\n services: result.operations\n .filter((o) => o.kind === 'service' && isCreate(o))\n .map((o) => o.id),\n events: result.operations\n .filter((o) => o.kind === 'event' && isCreate(o))\n .map((o) => o.id),\n channels: result.operations\n .filter((o) => o.kind === 'channel' && isCreate(o))\n .map((o) => o.id),\n };\n\n const sends: { service: string; event: string }[] = [];\n const receives: { service: string; event: string }[] = [];\n const messages: { channel: string; event: string }[] = [];\n for (const op of result.operations) {\n if (!isLink(op)) continue;\n if (op.kind === 'service-edge') {\n if (op.detail === 'receives') {\n const [service, event] = op.id.split('<-');\n if (service && event) receives.push({ service, event });\n } else {\n const [service, event] = op.id.split('->');\n if (service && event) sends.push({ service, event });\n }\n } else if (op.kind === 'channel-edge') {\n const [event, channel] = op.id.split('->');\n if (event && channel) messages.push({ channel, event });\n }\n }\n\n const schemaSources = {\n declared: result.operations.filter(\n (o) => o.kind === 'event' && o.schemaSource === 'declared',\n ).length,\n inferred: result.operations.filter(\n (o) => o.kind === 'event' && o.schemaSource === 'inferred',\n ).length,\n };\n\n const skipped = {\n services: result.operations\n .filter((o) => o.kind === 'service' && o.action === 'exists')\n .map((o) => o.id),\n events: result.operations\n .filter((o) => o.kind === 'event' && o.action === 'exists')\n .map((o) => o.id),\n channels: result.operations\n .filter((o) => o.kind === 'channel' && o.action === 'exists')\n .map((o) => o.id),\n };\n\n const totalCreated =\n created.services.length + created.events.length + created.channels.length;\n const totalLinked = sends.length + receives.length + messages.length;\n const totalSkipped =\n skipped.services.length + skipped.events.length + skipped.channels.length;\n\n return {\n spec: GENERATE_SUMMARY_SPEC,\n dryRun: options.dryRun,\n edgesOnly: options.edgesOnly,\n attempted: result.operations.length,\n totals: {\n created: totalCreated,\n linked: totalLinked,\n skipped: totalSkipped,\n },\n created,\n edges: { sends, receives, messages },\n schemaSources,\n skipped,\n };\n}\n\nexport function inferJsonSchemaFromObservation(\n observation: EventObservation,\n): Record<string, unknown> {\n const root: Record<string, unknown> = {\n $schema: 'http://json-schema.org/draft-07/schema#',\n type: 'object',\n properties: {},\n };\n\n const paths = new Set<string>(observation.fieldPaths);\n for (const path of Object.keys(observation.fieldStats ?? {})) {\n paths.add(path);\n }\n\n const sorted = [...paths].toSorted();\n const stats = observation.fieldStats ?? {};\n for (const path of sorted) {\n insertSchemaPath(root, path, stats[path]?.types ?? []);\n }\n return root;\n}\n\nfunction insertSchemaPath(\n root: Record<string, unknown>,\n path: string,\n observedTypes: string[],\n): void {\n if (!path) return;\n const steps = parsePath(path);\n let current = root;\n\n for (let i = 0; i < steps.length; i++) {\n const step = steps[i];\n const last = i === steps.length - 1;\n\n if (!current.properties || typeof current.properties !== 'object') {\n current.properties = {};\n }\n const properties = current.properties as Record<string, unknown>;\n const next =\n (properties[step.key] as Record<string, unknown> | undefined) ?? {};\n properties[step.key] = next;\n\n if (step.array) {\n next.type = 'array';\n const items =\n (next.items as Record<string, unknown> | undefined) ??\n ({} as Record<string, unknown>);\n next.items = items;\n if (!last && (!items.type || items.type === 'array')) {\n items.type = 'object';\n }\n current = items;\n } else {\n if (last && observedTypes.length > 0) {\n setType(next, observedTypes);\n } else {\n if (!next.type || next.type === 'array') next.type = 'object';\n }\n current = next;\n }\n }\n}\n\nfunction setType(schemaNode: Record<string, unknown>, types: string[]): void {\n const mapped = mapRuntimeTypes(types);\n if (mapped.length === 1) {\n schemaNode.type = mapped[0];\n } else if (mapped.length > 1) {\n schemaNode.type = mapped;\n }\n}\n\nfunction mapRuntimeTypes(types: string[]): string[] {\n const out = new Set<string>();\n for (const t of types) {\n switch (t) {\n case 'string':\n case 'number':\n case 'boolean':\n case 'object':\n case 'array':\n case 'null':\n out.add(t);\n break;\n default:\n break;\n }\n }\n return [...out];\n}\n\nfunction parsePath(path: string): Array<{ key: string; array: boolean }> {\n const segments = path.split('.');\n const out: Array<{ key: string; array: boolean }> = [];\n for (const segment of segments) {\n const isArray = segment.endsWith('[]');\n out.push({\n key: isArray ? segment.slice(0, -2) : segment,\n array: isArray,\n });\n }\n return out;\n}\n\nfunction collectServices(snapshot: ArchitectureSnapshot): Set<string> {\n const out = new Set<string>();\n for (const obs of Object.values(snapshot.events)) {\n if (obs.producer) out.add(obs.producer);\n for (const consumer of obs.consumers ?? []) out.add(consumer);\n }\n return out;\n}\n\nfunction collectChannels(snapshot: ArchitectureSnapshot): Set<string> {\n const out = new Set<string>();\n for (const obs of Object.values(snapshot.events)) {\n if (obs.channel) out.add(obs.channel);\n }\n return out;\n}\n\nconst GENERATED_MARKER = '<!-- autotel:generated -->';\n\nconst GENERATED_PREAMBLE = `${GENERATED_MARKER}\n<!-- Edit freely. Subsequent \\`autotel-eventcatalog generate\\` runs skip files that already exist. -->`;\n\nfunction buildEventMarkdown(\n snapshotName: string,\n obs: EventObservation,\n schemaSource: 'declared' | 'inferred',\n): string {\n const traceLine = obs.sampleTraceIds[0]\n ? `- Sample trace: \\`${obs.sampleTraceIds[0]}\\`\\n`\n : '';\n const producerLine = obs.producer ? `- Producer: \\`${obs.producer}\\`\\n` : '';\n const channelLine = obs.channel ? `- Channel: \\`${obs.channel}\\`\\n` : '';\n const sourceLine =\n schemaSource === 'declared'\n ? '- Schema source: declared at the `track()` call site (Zod)'\n : '- Schema source: inferred from observed `fieldStats` (no declared schema at the call site yet)';\n\n return `${GENERATED_PREAMBLE}\n\n## ${snapshotName}\n\n*Generated from autotel snapshot. Add a human description, examples, and ownership.*\n\n### Evidence\n- Observed **${obs.observedCount}** time${obs.observedCount === 1 ? '' : 's'}\n- First seen: \\`${obs.firstSeen}\\`\n- Last seen: \\`${obs.lastSeen}\\`\n${producerLine}${channelLine}${traceLine}${sourceLine}\n`;\n}\n\nfunction buildServiceMarkdown(\n serviceId: string,\n snapshot: ArchitectureSnapshot,\n): string {\n const sends = Object.entries(snapshot.events)\n .filter(([, obs]) => obs.producer === serviceId)\n .map(([name]) => `- \\`${name}\\``)\n .join('\\n');\n const sendsBlock = sends ? `### Sends\\n${sends}\\n` : '';\n\n return `${GENERATED_PREAMBLE}\n\n## ${serviceId}\n\n*Generated from autotel snapshot. Add a human description and ownership.*\n\n${sendsBlock}`;\n}\n\nfunction buildChannelMarkdown(\n channelId: string,\n snapshot: ArchitectureSnapshot,\n): string {\n const messages = Object.entries(snapshot.events)\n .filter(([, obs]) => obs.channel === channelId)\n .map(([name]) => `- \\`${name}\\``)\n .join('\\n');\n const messagesBlock = messages ? `### Carries\\n${messages}\\n` : '';\n\n return `${GENERATED_PREAMBLE}\n\n## ${channelId}\n\n*Generated from autotel snapshot. Add transport details, retention, schema registry, etc.*\n\n${messagesBlock}`;\n}\n\nfunction toCatalogEventId(snapshotEventName: string): string {\n return snapshotEventName\n .split(/[._\\-\\s]+/)\n .filter(Boolean)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join('');\n}\n\nfunction normaliseEventId(id: string): string {\n return id.toLowerCase().replaceAll(/[._\\-\\s]/g, '');\n}\n"],"mappings":";;;;;AAaA,MAAM,uBAAuB;;;;;;;;AAS7B,eAAsB,aACpB,MAC+B;CAC/B,IAAI;CACJ,IAAI;EACF,MAAM,MAAM,SAAS,MAAM,MAAM;CACnC,SAAS,KAAK;EACZ,IAAI,cAAc,GAAG,KAAK,IAAI,SAAS,UACrC,MAAM,IAAI,MAAM,uBAAuB,MAAM;EAE/C,IAAI,cAAc,GAAG,KAAK,IAAI,SAAS,UACrC,MAAM,IAAI,MAAM,6CAA6C,MAAM;EAErE,MAAM,IAAI,MACR,8BAA8B,KAAK,IAAK,IAAc,SACxD;CACF;CAEA,IAAI,IAAI,KAAK,CAAC,CAAC,WAAW,GACxB,MAAM,IAAI,MAAM,sBAAsB,MAAM;CAG9C,IAAI;CACJ,IAAI;EACF,SAAS,KAAK,MAAM,GAAG;CACzB,SAAS,KAAK;EACZ,MAAM,IAAI,MACR,+BAA+B,KAAK,IAAK,IAAc,QAAQ,EACjE;CACF;CAEA,OAAO,iBAAiB,QAAQ,IAAI;AACtC;;;;;;;AAQA,SAAS,iBAAiB,QAAiB,MAAoC;CAC7E,IAAI,CAAC,aAAa,MAAM,GACtB,MAAM,IAAI,MACR,mCAAmC,KAAK,QAAQ,SAAS,MAAM,EAAE,EACnE;CAGF,MAAM,EAAE,SAAS;CACjB,IAAI,OAAO,SAAS,YAAY,CAAC,KAAK,WAAW,oBAAoB,GAAG;EACtE,MAAM,QACJ,SAAS,SAAY,oBAAoB,QAAQ,SAAS,IAAI;EAChE,MAAM,IAAI,MACR,yCAAyC,KAAK,iCAAiC,qBAAqB,SAAS,MAAM,EACrH;CACF;CAKA,IAAI,CAAC,aAAa,OAAO,MAAM,GAC7B,MAAM,IAAI,MAAM,gDAAgD,MAAM;CAGxE,IAAI,OAAO,OAAO,YAAY,YAAY,OAAO,QAAQ,WAAW,GAClE,MAAM,IAAI,MAAM,kDAAkD,MAAM;CAG1E,IAAI,OAAO,OAAO,gBAAgB,UAChC,MAAM,IAAI,MACR,mEAAmE,MACrE;CAGF,KAAK,MAAM,CAAC,MAAM,gBAAgB,OAAO,QAAQ,OAAO,MAAM,GAAG;EAC/D,IAAI,CAAC,aAAa,WAAW,GAC3B,MAAM,IAAI,MACR,mBAAmB,KAAK,uBAAuB,KAAK,QAAQ,SAAS,WAAW,EAAE,EACpF;EAEF,IAAI,OAAO,YAAY,kBAAkB,UACvC,MAAM,IAAI,MACR,mBAAmB,KAAK,2CAA2C,MACrE;CAEJ;CAEA,OAAO;AACT;AAEA,SAAS,aAAa,OAAkD;CACtE,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAS,cAAc,KAA4C;CACjE,OACE,eAAe,SACf,OAAQ,IAA8B,SAAS;AAEnD;AAEA,SAAS,SAAS,OAAwB;CACxC,IAAI,UAAU,MAAM,OAAO;CAC3B,IAAI,MAAM,QAAQ,KAAK,GAAG,OAAO;CACjC,OAAO,OAAO,UAAU,WAAW,KAAK,UAAU,KAAK,IAAI,OAAO;AACpE;;;;ACzFA,eAAsB,iBACpB,aACuB;CACvB,MAAM,MAAM,MAAM,WAAW;CAE7B,MAAM,CAAC,QAAQ,UAAU,YAAY,MAAM,QAAQ,IAAI;EACrD,IAAI,UAAU;GAAE,YAAY;GAAM,cAAc;EAAK,CAAC;EACtD,IAAI,YAAY,EAAE,YAAY,KAAK,CAAC;EACpC,IAAI,YAAY,EAAE,YAAY,KAAK,CAAC;CACtC,CAAC;CAED,MAAM,QAAsB;EAC1B,wBAAQ,IAAI,IAAI;EAChB,0BAAU,IAAI,IAAI;EAClB,0BAAU,IAAI,IAAI;CACpB;CAIA,MAAM,kBAAkB,OAAO,IAAY,YAAqB;EAE9D,QAAO,MADa,IAAI,gBAAgB,aAAa,IAAI,OAAO,EACpD,EAAE,YAAY;CAC5B;CAEA,KAAK,MAAM,KAAK,UAAU,CAAC,GAAG;EAC5B,MAAM,WAAW,MAAM,gBAAgB,EAAE,IAAI,EAAE,OAAO;EACtD,MAAM,oBAAoB,EAAE,SACxB;GACE,oBAAoB,0BAA0B,EAAE,MAAM;GACtD,2BAA2B,iCAAiC,EAAE,MAAM;EACtE,IACA,CAAC;EACL,MAAM,OAAO,IAAI,EAAE,IAAI;GAAE,GAAG;GAAG;GAAU,GAAG;EAAkB,CAAC;CACjE;CAEA,KAAK,MAAM,KAAK,YAAY,CAAC,GAAG;EAC9B,MAAM,WAAW,MAAM,gBAAgB,EAAE,IAAI,EAAE,OAAO;EACtD,MAAM,SAAS,IAAI,EAAE,IAAI;GAAE,GAAG;GAAG;EAAS,CAAC;CAC7C;CAEA,KAAK,MAAM,KAAK,YAAY,CAAC,GAAG;EAC9B,MAAM,WAAW,MAAM,gBAAgB,EAAE,IAAI,EAAE,OAAO;EACtD,MAAM,SAAS,IAAI,EAAE,IAAI;GAAE,GAAG;GAAG;EAAS,CAAC;CAC7C;CAEA,OAAO;AACT;;;;;;AAOA,SAAgB,0BACd,QACA,SAAS,IACC;CACV,MAAM,sBAAM,IAAI,IAAY;CAC5B,WAAW,QAAQ,QAAQ,GAAG;CAC9B,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC,SAAS;AAC3B;AAEA,SAAS,WAAW,QAAiB,QAAgB,KAAwB;CAC3E,IAAI,CAAC,UAAU,OAAO,WAAW,UAAU;CAC3C,MAAM,IAAI;CAEV,IAAI,EAAE,cAAc,OAAO,EAAE,eAAe,UAC1C,KAAK,MAAM,CAAC,KAAK,QAAQ,OAAO,QAC9B,EAAE,UACJ,GAAG;EACD,MAAM,OAAO,WAAW,KAAK,MAAM,GAAG,OAAO,GAAG;EAChD,IAAI,IAAI,IAAI;EACZ,WAAW,KAAK,MAAM,GAAG;CAC3B;CAGF,IAAI,EAAE,OAAO;EACX,MAAM,cAAc,SAAS;EAC7B,WAAW,EAAE,OAAO,aAAa,GAAG;CACtC;AACF;AAEA,SAAgB,iCACd,QACA,SAAS,IACyB;CAClC,MAAM,sBAAM,IAAI,IAA8B;CAC9C,sBAAsB,QAAQ,QAAQ,GAAG;CACzC,MAAM,MAAwC,CAAC;CAC/C,KAAK,MAAM,CAAC,MAAM,MAAM,KAAK,IAAI,QAAQ;CACzC,OAAO;AACT;AAEA,SAAS,sBACP,QACA,QACA,KACM;CACN,IAAI,CAAC,UAAU,OAAO,WAAW,UAAU;CAC3C,MAAM,IAAI;CACV,MAAM,UAAU,EAAE;CAClB,MAAM,UAAU,EAAE;CAClB,IAAI,WAAW,OAAO,YAAY,UAAa,YAAY,SAAY;EACrE,MAAM,QAAQ,YAAY,OAAO;EACjC,MAAM,aAAa,MAAM,QAAQ,OAAO,IAAI,CAAC,GAAG,OAAO,IAAI;EAC3D,IAAI,IAAI,QAAQ;GACd,GAAI,MAAM,SAAS,IAAI,EAAE,MAAM,IAAI,CAAC;GACpC,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;EACrC,CAAC;CACH;CAEA,IAAI,EAAE,cAAc,OAAO,EAAE,eAAe,UAC1C,KAAK,MAAM,CAAC,KAAK,QAAQ,OAAO,QAC9B,EAAE,UACJ,GAEE,sBAAsB,KADT,WAAW,KAAK,MAAM,GAAG,OAAO,GAAG,OACf,GAAG;CAGxC,IAAI,EAAE,OAAO;EACX,MAAM,cAAc,SAAS;EAC7B,sBAAsB,EAAE,OAAO,aAAa,GAAG;CACjD;AACF;AAEA,SAAS,YAAY,SAA4B;CAC/C,IAAI,OAAO,YAAY,UAAU,OAAO,CAAC,OAAO;CAChD,IAAI,MAAM,QAAQ,OAAO,GACvB,OAAO,QAAQ,QAAQ,MAAmB,OAAO,MAAM,QAAQ,CAAC,CAAC,SAAS;CAE5E,OAAO,CAAC;AACV;;;;;ACvGA,SAAgB,SAAS,QAA8B;CAErD,OADU,iBAAiB,MACpB,CAAC,CAAC,QAAQ;AACnB;AAsBA,SAAgB,iBAAiB,QAAkC;CACjE,MAAM,YAAY,OAAO,OAAO,aAAa,CAAC;CAC9C,MAAM,aAAa,OAAO,OAAO,cAAc,CAAC;CAChD,MAAM,mBAAmB,OAAO,OAAO,WAAW;CAClD,MAAM,kBAAkB,OAAO,OAAO,WAAW,QAC9C,KAAK,OAAO,MAAM,GAAG,MAAM,SAAS,GAAG,QAAQ,QAChD,CACF;CACA,MAAM,iBAAiB,UAAU;CACjC,MAAM,kBAAkB,WAAW;CACnC,MAAM,gCACJ,OAAO,OAAO,wBAAwB;CACxC,MAAM,4BAA4B,OAAO,OAAO,oBAAoB;CACpE,MAAM,uBAAuB,OAAO,SAAS,wBAAwB;CACrE,MAAM,uBAAuB,OAAO,SAAS,wBAAwB;CAErE,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,OACE,gCACA,4BACA,kBACA,iBACA,kBACA,uBACA;CACJ;AACF;AAEA,SAAgB,2BACd,UACA,SACa;CACb,MAAM,iBAAiB,IAAI,IAAI,OAAO,KAAK,SAAS,MAAM,CAAC;CAC3D,MAAM,kBAAkB,IAAI,IAAI,QAAQ,OAAO,KAAK,CAAC;CAKrD,MAAM,2CAA2B,IAAI,IAAoB;CACzD,KAAK,MAAM,MAAM,iBACf,yBAAyB,IAAIA,mBAAiB,EAAE,GAAG,EAAE;CAGvD,MAAM,0BAAoC,CAAC;CAC3C,MAAM,oCAAoB,IAAI,IAAY;CAC1C,KAAK,MAAM,QAAQ,gBAAgB;EACjC,MAAM,UAAU,yBAAyB,IAAIA,mBAAiB,IAAI,CAAC;EACnE,IAAI,SACF,kBAAkB,IAAI,OAAO;OAE7B,wBAAwB,KAAK,IAAI;CAErC;CAEA,MAAM,sBAAgC,CAAC;CACvC,KAAK,MAAM,MAAM,iBACf,IAAI,CAAC,kBAAkB,IAAI,EAAE,GAAG,oBAAoB,KAAK,EAAE;CAG7D,MAAM,aAA2B,CAAC;CAClC,MAAM,YAAyB,CAAC;CAChC,MAAM,aAA2B,CAAC;CAClC,KAAK,MAAM,CAAC,UAAU,QAAQ,OAAO,QAAQ,SAAS,MAAM,GAAG;EAC7D,MAAM,YAAY,yBAAyB,IAAIA,mBAAiB,QAAQ,CAAC;EACzE,IAAI,CAAC,WAAW;EAChB,MAAM,YAAY,QAAQ,OAAO,IAAI,SAAS;EAC9C,MAAM,WAAW,WAAW;EAC5B,IAAI,CAAC,UAAU;EAEf,MAAM,cAAc,IAAI,IAAI,QAAQ;EACpC,MAAM,cAAc,IAAI,IAAI,IAAI,UAAU;EAE1C,MAAM,QAAQ,IAAI,WAAW,QAAQ,MAAM,CAAC,YAAY,IAAI,CAAC,CAAC;EAC9D,MAAM,UAAU,SAAS,QAAQ,MAAM,CAAC,YAAY,IAAI,CAAC,CAAC;EAE1D,IAAI,MAAM,SAAS,KAAK,QAAQ,SAAS,GACvC,WAAW,KAAK;GAAE,OAAO;GAAU;GAAO;EAAQ,CAAC;EAGrD,MAAM,cAAc,WAAW,6BAA6B,CAAC;EAC7D,MAAM,QAAQ,IAAI,cAAc,CAAC;EACjC,KAAK,MAAM,CAAC,MAAM,uBAAuB,OAAO,QAAQ,WAAW,GAAG;GACpE,MAAM,WAAW,MAAM;GACvB,IAAI,CAAC,UAAU;GACf,IAAI,mBAAmB,SAAS,mBAAmB,MAAM,SAAS,GAAG;IAKnE,MAAM,UAAU,oBAAoB,mBAAmB,KAAK;IAC5D,MAAM,WAAW,SAAS,MAAM,QAAQ,MAAc,CAAC,QAAQ,IAAI,CAAC,CAAC;IAIrE,MAAM,oBAFJ,mBAAmB,MAAM,SAAS,SAAS,KAC3C,CAAC,mBAAmB,MAAM,SAAS,QAAQ,IAEzC,SAAS,aAAa,QACnB,MAAe,OAAO,MAAM,YAAY,CAAC,OAAO,UAAU,CAAC,CAC9D,IACA,CAAC;IACL,IAAI,SAAS,SAAS,KAAK,kBAAkB,SAAS,GACpD,UAAU,KAAK;KACb,OAAO;KACP;KACA,UAAU,mBAAmB;KAC7B,UAAU,CAAC,GAAG,IAAI,IAAI,SAAS,KAAK,CAAC,CAAC,CAAC,SAAS;IAClD,CAAC;GAEL;GACA,IACE,mBAAmB,cACnB,mBAAmB,WAAW,SAAS,KACvC,SAAS,aAAa,SAAS,GAC/B;IACA,MAAM,sBAAsB,SAAS,aAAa,QAC/C,MACC,CAAC,mBAAmB,YAAY,MAAM,MAAM,OAAO,GAAG,GAAG,CAAC,CAAC,CAC/D;IACA,IAAI,oBAAoB,SAAS,GAC/B,WAAW,KAAK;KACd,OAAO;KACP;KACA,UAAU,mBAAmB;KAC7B,UAAU,CAAC,GAAG,IAAI,IAAI,mBAAmB,CAAC;IAC5C,CAAC;GAEL;EACF;CACF;CAEA,MAAM,mBAAmB,iBAAiB,QAAQ;CAClD,MAAM,oBAAoB,IAAI,IAAI,QAAQ,SAAS,KAAK,CAAC;CACzD,MAAM,uBAAuB,CAAC,GAAG,gBAAgB,CAAC,CAAC,QAChD,OAAO,CAAC,kBAAkB,IAAI,EAAE,CACnC;CAEA,MAAM,mBAAmBC,kBAAgB,QAAQ;CACjD,MAAM,oBAAoB,IAAI,IAAI,QAAQ,SAAS,KAAK,CAAC;CACzD,MAAM,uBAAuB,CAAC,GAAG,gBAAgB,CAAC,CAAC,QAChD,OAAO,CAAC,kBAAkB,IAAI,EAAE,CACnC;CAEA,OAAO;EACL,qBAAqB,SAAS;EAC9B,iBAAiB,SAAS;EAC1B,QAAQ;GACN,yBAAyB,wBAAwB,KAAK;GACtD,qBAAqB,oBAAoB,KAAK;GAC9C,YAAY,WAAW,MAAM,GAAG,MAAM,EAAE,MAAM,cAAc,EAAE,KAAK,CAAC;GACpE,WAAW,UAAU,MAAM,GAAG,MAC5B,GAAG,EAAE,MAAM,GAAG,EAAE,OAAO,cAAc,GAAG,EAAE,MAAM,GAAG,EAAE,MAAM,CAC7D;GACA,YAAY,WAAW,MAAM,GAAG,MAC9B,GAAG,EAAE,MAAM,GAAG,EAAE,OAAO,cAAc,GAAG,EAAE,MAAM,GAAG,EAAE,MAAM,CAC7D;EACF;EACA,UAAU,EAAE,yBAAyB,qBAAqB,KAAK,EAAE;EACjE,UAAU,EAAE,yBAAyB,qBAAqB,KAAK,EAAE;CACnE;AACF;;;;;;;;AASA,SAAS,oBAAoB,UAAiC;CAC5D,MAAM,UAAU,IAAI,IAAY,QAAQ;CACxC,IAAI,SAAS,SAAS,SAAS,GAAG,QAAQ,IAAI,QAAQ;CACtD,OAAO;AACT;AAEA,SAASD,mBAAiB,IAAoB;CAE5C,OAAO,GAAG,YAAY,CAAC,CAAC,WAAW,aAAa,EAAE;AACpD;AAEA,SAAS,iBAAiB,UAA6C;CACrE,MAAM,sBAAM,IAAI,IAAY;CAC5B,KAAK,MAAM,OAAO,OAAO,OAAO,SAAS,MAAM,GAC7C,IAAI,IAAI,UAAU,IAAI,IAAI,IAAI,QAAQ;CAExC,OAAO;AACT;AAEA,SAASC,kBAAgB,UAA6C;CACpE,MAAM,sBAAM,IAAI,IAAY;CAC5B,KAAK,MAAM,OAAO,OAAO,OAAO,SAAS,MAAM,GAC7C,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,OAAO;CAEtC,OAAO;AACT;;;;AChQA,SAAgB,oBACd,MACA,MACY;CACZ,MAAM,mBAAmB,eACvB,KAAK,OAAO,yBACZ,KAAK,OAAO,uBACd;CACA,MAAM,oBAAoB,eACxB,KAAK,OAAO,qBACZ,KAAK,OAAO,mBACd;CACA,MAAM,uBAAuB,eAC3B,KAAK,OAAO,YACZ,KAAK,OAAO,UACd;CACA,MAAM,qBAAqB,eACzB,KAAK,SAAS,yBACd,KAAK,SAAS,uBAChB;CACA,MAAM,qBAAqB,eACzB,KAAK,SAAS,yBACd,KAAK,SAAS,uBAChB;CAEA,MAAM,aAA2B;EAC/B,QAAQ;GACN,yBAAyB,iBAAiB;GAC1C,qBAAqB,kBAAkB;GACvC,YAAY,qBAAqB;GACjC,WAAW,cACT,KAAK,OAAO,aAAa,CAAC,GAC1B,KAAK,OAAO,aAAa,CAAC,CAC5B,CAAC,CAAC;GACF,YAAY,eACV,KAAK,OAAO,cAAc,CAAC,GAC3B,KAAK,OAAO,cAAc,CAAC,CAC7B,CAAC,CAAC;EACJ;EACA,UAAU,EAAE,yBAAyB,mBAAmB,MAAM;EAC9D,UAAU,EAAE,yBAAyB,mBAAmB,MAAM;CAChE;CA6BA,OAAO;EAAE;EAAY;GA1BnB,QAAQ;IACN,yBAAyB,iBAAiB;IAC1C,qBAAqB,kBAAkB;IACvC,YAAY,qBAAqB;IACjC,WAAW,cACT,KAAK,OAAO,aAAa,CAAC,GAC1B,KAAK,OAAO,aAAa,CAAC,CAC5B,CAAC,CAAC;IACF,YAAY,eACV,KAAK,OAAO,cAAc,CAAC,GAC3B,KAAK,OAAO,cAAc,CAAC,CAC7B,CAAC,CAAC;GACJ;GACA,UAAU,EAAE,yBAAyB,mBAAmB,QAAQ;GAChE,UAAU,EAAE,yBAAyB,mBAAmB,QAAQ;EAYtC;EAAG,aAR7B,WAAW,OAAO,wBAAwB,SAAS,KACnD,WAAW,OAAO,oBAAoB,SAAS,KAC/C,WAAW,OAAO,WAAW,SAAS,KACtC,WAAW,OAAO,UAAU,SAAS,KACrC,WAAW,OAAO,WAAW,SAAS,KACtC,WAAW,SAAS,wBAAwB,SAAS,KACrD,WAAW,SAAS,wBAAwB,SAAS;CAEZ;AAC7C;;;;;;AAOA,SAAgB,kBAAkB,SAAoC;CACpE,MAAM,mBAAmB,QAAQ,OAAO,WAAW;CACnD,MAAM,kBAAkB,QAAQ,OAAO,WAAW,QAC/C,KAAK,OAAO,MAAM,GAAG,MAAM,SAAS,GAAG,QAAQ,QAChD,CACF;CACA,MAAM,gCACJ,QAAQ,OAAO,wBAAwB;CACzC,MAAM,4BAA4B,QAAQ,OAAO,oBAAoB;CACrE,MAAM,uBAAuB,QAAQ,SAAS,wBAAwB;CACtE,MAAM,uBAAuB,QAAQ,SAAS,wBAAwB;CACtE,MAAM,kBAAkB,QAAQ,OAAO,aAAa,CAAC,EAAC,CAAE;CACxD,MAAM,mBAAmB,QAAQ,OAAO,cAAc,CAAC,EAAC,CAAE;CAE1D,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,OACE,gCACA,4BACA,kBACA,iBACA,kBACA,uBACA;CACJ;AACF;AAEA,SAAgB,gBAAgB,OAG9B;CACA,OAAO;EACL,YAAY,kBAAkB,MAAM,UAAU;EAC9C,UAAU,kBAAkB,MAAM,QAAQ;CAC5C;AACF;AAEA,SAAS,eACP,MACA,MACwC;CACxC,MAAM,UAAU,IAAI,IAAI,IAAI;CAC5B,MAAM,UAAU,IAAI,IAAI,IAAI;CAC5B,OAAO;EACL,OAAO,KAAK,QAAQ,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK;EAChD,SAAS,KAAK,QAAQ,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK;CACpD;AACF;AAEA,SAAS,eACP,MACA,MACgD;CAChD,MAAM,cAAc,IAAI,IAAI,KAAK,KAAK,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;CACzD,MAAM,cAAc,IAAI,IAAI,KAAK,KAAK,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;CAEzD,MAAM,QAAsB,CAAC;CAC7B,MAAM,UAAwB,CAAC;CAE/B,KAAK,MAAM,CAAC,OAAO,MAAM,aAAa;EACpC,MAAM,IAAI,YAAY,IAAI,KAAK;EAC/B,IAAI,CAAC,GAAG;GAEN,MAAM,KAAK,CAAC;GACZ;EACF;EACA,MAAM,aAAa,EAAE,MAAM,QAAQ,MAAM,CAAC,EAAE,MAAM,SAAS,CAAC,CAAC;EAC7D,MAAM,eAAe,EAAE,QAAQ,QAAQ,MAAM,CAAC,EAAE,QAAQ,SAAS,CAAC,CAAC;EACnE,IAAI,WAAW,SAAS,KAAK,aAAa,SAAS,GACjD,MAAM,KAAK;GAAE;GAAO,OAAO;GAAY,SAAS;EAAa,CAAC;CAElE;CAEA,KAAK,MAAM,CAAC,OAAO,MAAM,aAAa;EACpC,MAAM,IAAI,YAAY,IAAI,KAAK;EAC/B,IAAI,CAAC,GAAG;GACN,QAAQ,KAAK,CAAC;GACd;EACF;EACA,MAAM,eAAe,EAAE,MAAM,QAAQ,MAAM,CAAC,EAAE,MAAM,SAAS,CAAC,CAAC;EAC/D,MAAM,iBAAiB,EAAE,QAAQ,QAAQ,MAAM,CAAC,EAAE,QAAQ,SAAS,CAAC,CAAC;EACrE,IAAI,aAAa,SAAS,KAAK,eAAe,SAAS,GACrD,QAAQ,KAAK;GAAE;GAAO,OAAO;GAAc,SAAS;EAAe,CAAC;CAExE;CAEA,OAAO;EAAE;EAAO;CAAQ;AAC1B;AAEA,SAAS,cACP,MACA,MAC8C;CAC9C,OAAO,oBAAoB,MAAM,OAAO,MAAM,GAAG,EAAE,MAAM,IAAI,EAAE,MAAM;AACvE;AAEA,SAAS,eACP,MACA,MACgD;CAChD,OAAO,oBAAoB,MAAM,OAAO,MAAM,GAAG,EAAE,MAAM,IAAI,EAAE,MAAM;AACvE;AAEA,SAAS,oBACP,MACA,MACA,OAC8B;CAC9B,MAAM,UAAU,IAAI,IAAI,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;CACtD,MAAM,UAAU,IAAI,IAAI,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;CACtD,MAAM,QAAa,CAAC;CACpB,MAAM,UAAe,CAAC;CAEtB,KAAK,MAAM,CAAC,GAAG,OAAO,SAAS;EAC7B,MAAM,KAAK,QAAQ,IAAI,CAAC;EACxB,IAAI,CAAC,MAAM,KAAK,UAAU,EAAE,MAAM,KAAK,UAAU,EAAE,GAAG,MAAM,KAAK,EAAE;CACrE;CACA,KAAK,MAAM,CAAC,GAAG,OAAO,SAAS;EAC7B,MAAM,KAAK,QAAQ,IAAI,CAAC;EACxB,IAAI,CAAC,MAAM,KAAK,UAAU,EAAE,MAAM,KAAK,UAAU,EAAE,GAAG,QAAQ,KAAK,EAAE;CACvE;CACA,OAAO;EAAE;EAAO;CAAQ;AAC1B;;;;ACzOA,SAAgB,eAAe,QAA6B;CAC1D,MAAM,QAAkB;EACtB;EACA;EACA,oBAAoB,OAAO,gBAAgB,QAAQ,OAAO,oBAAoB;EAC9E;CACF;CAEA,IAAI,CAAC,SAAS,MAAM,GAAG;EACrB,MAAM,KAAK,iDAAiD,EAAE;EAC9D,OAAO,MAAM,KAAK,IAAI;CACxB;CAEA,IAAI,OAAO,OAAO,wBAAwB,SAAS,GAAG;EACpD,MAAM,KACJ,uCACA,IACA,kEACA,0DACA,EACF;EACA,KAAK,MAAM,QAAQ,OAAO,OAAO,yBAC/B,MAAM,KAAK,OAAO,KAAK,GAAG;EAE5B,MAAM,KAAK,EAAE;CACf;CAEA,IAAI,OAAO,OAAO,oBAAoB,SAAS,GAAG;EAChD,MAAM,KACJ,2CACA,IACA,kEACA,wEACA,EACF;EACA,KAAK,MAAM,QAAQ,OAAO,OAAO,qBAC/B,MAAM,KAAK,OAAO,KAAK,GAAG;EAE5B,MAAM,KAAK,EAAE;CACf;CAEA,IAAI,OAAO,OAAO,WAAW,SAAS,GAAG;EACvC,MAAM,KAAK,uBAAuB,EAAE;EACpC,KAAK,MAAM,SAAS,OAAO,OAAO,YAAY;GAC5C,MAAM,KAAK,SAAS,MAAM,MAAM,KAAK,EAAE;GACvC,IAAI,MAAM,MAAM,SAAS,GAAG;IAC1B,MAAM,KACJ,0DACA,EACF;IACA,KAAK,MAAM,KAAK,MAAM,OAAO,MAAM,KAAK,OAAO,EAAE,GAAG;IACpD,MAAM,KAAK,EAAE;GACf;GACA,IAAI,MAAM,QAAQ,SAAS,GAAG;IAC5B,MAAM,KAAK,2CAA2C,EAAE;IACxD,KAAK,MAAM,KAAK,MAAM,SAAS,MAAM,KAAK,OAAO,EAAE,GAAG;IACtD,MAAM,KAAK,EAAE;GACf;EACF;CACF;CAEA,KAAK,OAAO,OAAO,aAAa,CAAC,EAAC,CAAE,SAAS,GAAG;EAC9C,MAAM,KAAK,iBAAiB,EAAE;EAC9B,KAAK,MAAM,SAAS,OAAO,OAAO,aAAa,CAAC,GAC9C,MAAM,KACJ,OAAO,MAAM,MAAM,OAAO,MAAM,KAAK,KACrC,iBAAiB,MAAM,SAAS,KAAK,KAAK,EAAE,kBAAkB,MAAM,SAAS,KAAK,KAAK,EAAE,GAC3F;EAEF,MAAM,KAAK,EAAE;CACf;CAEA,KAAK,OAAO,OAAO,cAAc,CAAC,EAAC,CAAE,SAAS,GAAG;EAC/C,MAAM,KAAK,kBAAkB,EAAE;EAC/B,KAAK,MAAM,SAAS,OAAO,OAAO,cAAc,CAAC,GAC/C,MAAM,KACJ,OAAO,MAAM,MAAM,OAAO,MAAM,KAAK,KACrC,sBAAsB,MAAM,SAAS,KAAK,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,kBAAkB,MAAM,SAAS,KAAK,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,GAC1J;EAEF,MAAM,KAAK,EAAE;CACf;CAEA,IAAI,OAAO,SAAS,wBAAwB,SAAS,GAAG;EACtD,MAAM,KAAK,yCAAyC,EAAE;EACtD,KAAK,MAAM,MAAM,OAAO,SAAS,yBAC/B,MAAM,KAAK,OAAO,GAAG,GAAG;EAE1B,MAAM,KAAK,EAAE;CACf;CAEA,IAAI,OAAO,SAAS,wBAAwB,SAAS,GAAG;EACtD,MAAM,KAAK,yCAAyC,EAAE;EACtD,KAAK,MAAM,MAAM,OAAO,SAAS,yBAC/B,MAAM,KAAK,OAAO,GAAG,GAAG;EAE1B,MAAM,KAAK,EAAE;CACf;CAEA,OAAO,MAAM,KAAK,IAAI;AACxB;;;;;AAMA,SAAgB,oBAAoB,OAA2B;CAC7D,MAAM,QAAkB,CACtB,qDACA,EACF;CAEA,IAAI,CAAC,MAAM,aAAa;EAEtB,IADiB,kBAAkB,MAAM,QAC9B,GAAG;GACZ,MAAM,KAAK,2DAA2D,EAAE;GACxE,cAAc,MAAM,UAAU,OAAO,EAAE,MAAM,IAAI,CAAC;EACpD,OACE,MAAM,KAAK,mDAAmD;EAEhE,MAAM,KAAK,EAAE;EACb,OAAO,MAAM,KAAK,IAAI;CACxB;CAEA,MAAM,KAAK,iCAAiC,EAAE;CAC9C,cAAc,MAAM,YAAY,OAAO,EAAE,MAAM,IAAI,CAAC;CAEpD,IAAI,kBAAkB,MAAM,QAAQ,GAAG;EACrC,MAAM,KAAK,IAAI,+BAA+B,EAAE;EAChD,cAAc,MAAM,UAAU,OAAO,EAAE,MAAM,IAAI,CAAC;CACpD;CAEA,OAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,kBAAkB,GAA0B;CACnD,OACE,EAAE,OAAO,wBAAwB,SAAS,KAC1C,EAAE,OAAO,oBAAoB,SAAS,KACtC,EAAE,OAAO,WAAW,SAAS,MAC5B,EAAE,OAAO,aAAa,CAAC,EAAC,CAAE,SAAS,MACnC,EAAE,OAAO,cAAc,CAAC,EAAC,CAAE,SAAS,KACrC,EAAE,SAAS,wBAAwB,SAAS,KAC5C,EAAE,SAAS,wBAAwB,SAAS;AAEhD;AAEA,SAAS,cACP,SACA,KACA,SACM;CACN,IAAI,QAAQ,OAAO,wBAAwB,SAAS,GAAG;EACrD,IAAI,KAAK,wCAAwC,EAAE;EACnD,KAAK,MAAM,KAAK,QAAQ,OAAO,yBAC7B,IAAI,KAAK,OAAO,EAAE,GAAG;EAEvB,IAAI,KAAK,EAAE;CACb;CACA,IAAI,QAAQ,OAAO,oBAAoB,SAAS,GAAG;EACjD,IAAI,KAAK,4CAA4C,EAAE;EACvD,KAAK,MAAM,KAAK,QAAQ,OAAO,qBAC7B,IAAI,KAAK,OAAO,EAAE,GAAG;EAEvB,IAAI,KAAK,EAAE;CACb;CACA,KAAK,MAAM,MAAM,QAAQ,OAAO,YAAY;EAC1C,IAAI,KAAK,sBAAsB,GAAG,MAAM,OAAO,EAAE;EACjD,KAAK,MAAM,KAAK,GAAG,OAAO,IAAI,KAAK,KAAK,QAAQ,KAAK,KAAK,EAAE,WAAW;EACvE,KAAK,MAAM,KAAK,GAAG,SACjB,IAAI,KAAK,KAAK,QAAQ,KAAK,KAAK,EAAE,aAAa;EACjD,IAAI,KAAK,EAAE;CACb;CACA,KAAK,MAAM,MAAM,QAAQ,OAAO,aAAa,CAAC,GAC5C,IAAI,KACF,qBAAqB,GAAG,MAAM,OAAO,GAAG,KAAK,OAC7C,IACA,KAAK,QAAQ,KAAK,cAAc,GAAG,SAAS,KAAK,KAAK,EAAE,iBAAiB,GAAG,SAAS,KAAK,KAAK,EAAE,KACjG,EACF;CAEF,KAAK,MAAM,MAAM,QAAQ,OAAO,cAAc,CAAC,GAC7C,IAAI,KACF,sBAAsB,GAAG,MAAM,OAAO,GAAG,KAAK,OAC9C,IACA,KAAK,QAAQ,KAAK,mBAAmB,GAAG,SAAS,KAAK,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,iBAAiB,GAAG,SAAS,KAAK,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,KAChK,EACF;CAEF,IAAI,QAAQ,SAAS,wBAAwB,SAAS,GAAG;EACvD,IAAI,KAAK,0CAA0C,EAAE;EACrD,KAAK,MAAM,MAAM,QAAQ,SAAS,yBAChC,IAAI,KAAK,OAAO,GAAG,GAAG;EAExB,IAAI,KAAK,EAAE;CACb;CACA,IAAI,QAAQ,SAAS,wBAAwB,SAAS,GAAG;EACvD,IAAI,KAAK,0CAA0C,EAAE;EACrD,KAAK,MAAM,MAAM,QAAQ,SAAS,yBAChC,IAAI,KAAK,OAAO,GAAG,GAAG;EAExB,IAAI,KAAK,EAAE;CACb;AAIF;AAEA,MAAa,mBAA6B;CACxC,MAAM;CACN,aACE;CACF,cAAc;CACd,aAAa;AACf;;;;ACrNA,SAAgB,eAAe,QAA6B;CAC1D,OAAO,yBAAyB,eAAe,MAAM,CAAC;AACxD;AAEA,SAAgB,oBAAoB,OAA2B;CAC7D,OAAO,yBAAyB,oBAAoB,KAAK,CAAC;AAC5D;AAEA,SAAS,yBAAyB,IAAoB;CACpD,OAAO,GACJ,WAAW,YAAY,EAAE,CAAC,CAC1B,WAAW,KAAK,EAAE,CAAC,CACnB,WAAW,oBAAoB,IAAI;AACxC;AAEA,MAAa,mBAA6B;CACxC,MAAM;CACN,aAAa;CACb,cAAc;CACd,aAAa;AACf;;;;;;;;AChBA,MAAa,cAAc;AAQ3B,SAAgB,WAAW,MAA0B;CACnD,MAAM,WAA+B;EAAE,MAAM;EAAa,GAAG;CAAK;CAClE,OAAO,KAAK,UAAU,UAAU,MAAM,CAAC;AACzC;AAEA,MAAa,eAAyB;CACpC,MAAM;CACN,aACE;CACF,eAAe,WAAW,WAAW;EAAE,MAAM;EAAO;CAAO,CAAC;CAC5D,cAAc,UAAU,WAAW;EAAE,MAAM;EAAY;CAAM,CAAC;AAChE;;;;ACWA,SAAgB,yBACd,QAC0B;CAM1B,OAAO,uBAAuB;EAJ5B,QAAQ,OAAO;EACf,UAAU,OAAO;EACjB,UAAU,OAAO;CAEiB,GAAG,OAAO,qBAAqB,SAAS;AAC9E;AAEA,SAAgB,wBACd,OAC0B;CAC1B,OAAO,uBACL,MAAM,6BACN,IAAI,KAAK,CAAC,EAAC,CAAC,YAAY,GACxB,mBACF;AACF;AAEA,SAAS,uBACP,SACA,WACA,OAC0B;CAC1B,MAAM,YAA8B,CAAC;CACrC,MAAM,gBAAsC,CAAC;CAE7C,KAAK,MAAM,aAAa,QAAQ,OAAO,yBACrC,UAAU,KAAK;EACb,YAAY;EACZ,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CAGH,KAAK,MAAM,aAAa,QAAQ,OAAO,qBACrC,UAAU,KAAK;EACb,YAAY;EACZ,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CAGH,KAAK,MAAM,SAAS,QAAQ,OAAO,YACjC,UAAU,KAAK;EACb,YAAY,MAAM;EAClB,SAAS;EACT,MAAM;EACN,YAAY;EACZ,eAAe,CACb,GAAG,MAAM,MAAM,KAAK,MAAM,SAAS,GAAG,GACtC,GAAG,MAAM,QAAQ,KAAK,MAAM,WAAW,GAAG,CAC5C;CACF,CAAC;CAGH,KAAK,MAAM,SAAS,QAAQ,OAAO,aAAa,CAAC,GAC/C,UAAU,KAAK;EACb,YAAY,MAAM;EAClB,SAAS;EACT,MAAM;EACN,YAAY;EACZ,eAAe,CAAC,QAAQ,MAAM,MAAM;CACtC,CAAC;CAGH,KAAK,MAAM,SAAS,QAAQ,OAAO,cAAc,CAAC,GAChD,UAAU,KAAK;EACb,YAAY,MAAM;EAClB,SAAS;EACT,MAAM;EACN,YAAY;EACZ,eAAe,CAAC,QAAQ,MAAM,MAAM;CACtC,CAAC;CAGH,KAAK,MAAM,aAAa,QAAQ,SAAS,yBACvC,UAAU,KAAK;EACb,YAAY;EACZ,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CAGH,KAAK,MAAM,aAAa,QAAQ,SAAS,yBACvC,UAAU,KAAK;EACb,YAAY;EACZ,SAAS;EACT,MAAM;EACN,YAAY;CACd,CAAC;CAGH,MAAM,UAAU;EACd,cAAc,UAAU,SAAS,cAAc;EAC/C,gBAAgB,UAAU,QAAQ,MAAM,EAAE,eAAe,OAAO,CAAC,CAAC;EAClE,kBAAkB,UAAU,QAAQ,MAAM,EAAE,eAAe,SAAS,CAAC,CAClE;EACH,mBAAmB,UAAU,QAAQ,MAAM,EAAE,eAAe,UAAU,CAAC,CACpE;EACH,oBAAoB,UAAU,QAAQ,MAAM,EAAE,eAAe,WAAW,CAAC,CACtE;EACH,oBAAoB,cAAc,QAAQ,MAAM,EAAE,eAAe,OAAO,CAAC,CACtE;EACH,sBAAsB,cAAc,QACjC,MAAM,EAAE,eAAe,SAC1B,CAAC,CAAC;CACJ;CAEA,OAAO;EACL,WAAW;GAAE,OAAO;GAAW,4BAAW,IAAI,KAAK,CAAC,EAAC,CAAC,YAAY;EAAE;EACpE,WAAW;GAAE;GAAO;EAAU;EAC9B;EACA;EACA;CACF;AACF;;;;AC5JA,MAAa,kCACX;AAQF,SAAgB,yCACd,QACQ;CACR,MAAM,WAA6C;EACjD,MAAM;EACN,MAAM;EACN,MAAM,yBAAyB,MAAM;CACvC;CACA,OAAO,KAAK,UAAU,UAAU,MAAM,CAAC;AACzC;AAEA,SAAgB,wCACd,OACQ;CACR,MAAM,WAA6C;EACjD,MAAM;EACN,MAAM;EACN,MAAM,wBAAwB,KAAK;CACrC;CACA,OAAO,KAAK,UAAU,UAAU,MAAM,CAAC;AACzC;AAEA,MAAa,mCAA6C;CACxD,MAAM;CACN,aACE;CACF,cAAc;CACd,aAAa;AACf;;;;ACnCA,MAAM,oBAAyC;CAC7C;CACA;CACA;CACA;AACF;AAEA,MAAM,iBAA6B,CAAC;;;;;AAMpC,MAAa,YAAiC;;;;;;;AAQ9C,MAAa,iBAAiB;CAC5B;CACA;CACA;CACA;AACF;AAIA,SAAgB,YAAY,MAAoC;CAC9D,OAAO,cAAc,CAAC,CAAC,MAAM,MAAM,EAAE,SAAS,IAAI;AACpD;AAEA,SAAgB,gBAAqC;CACnD,OAAO,CAAC,GAAG,mBAAmB,GAAG,cAAc;AACjD;AAEA,SAAgB,oBAAuC;CACrD,OAAO,cAAc,CAAC,CAAC,KAAK,MAAM,EAAE,IAAI;AAC1C;;;;;;AAOA,SAAgB,iBAAiB,UAA0B;CACzD,IAAI,YAAY,SAAS,IAAI,GAC3B,MAAM,IAAI,MACR,kBAAkB,SAAS,KAAK,0FAClC;CAEF,eAAe,KAAK,QAAQ;AAC9B;;;;AC3CA,SAAgB,eACd,OACwB;CACxB,IAAI,MAAM,SAAS,OAAO;EACxB,MAAM,aAAa,SAAS,MAAM,MAAM;EACxC,OAAO;GACL;GACA,QAAQ,aACJ,wCACA;EACN;CACF;CACA,MAAM,aAAa,MAAM,MAAM;CAC/B,OAAO;EACL;EACA,QAAQ,aACJ,wDACA;CACN;AACF;;;;ACvBA,MAAa,cAAc;AAC3B,MAAa,YAAY;AAyCzB,eAAsB,aAAa,MAA0C;CAC3E,MAAM,EAAE,UAAU,aAAa,SAAS,UAAU;CAClD,MAAM,UAAU,MAAM,iBAAiB,WAAW;CAElD,MAAM,sCAAsB,IAAI,IAG9B;CACF,KAAK,MAAM,CAAC,IAAI,OAAO,QAAQ,QAC7B,oBAAoB,IAAIC,mBAAiB,EAAE,GAAG;EAC5C;EACA,UAAU,GAAG;CACf,CAAC;CAGH,MAAM,UAAyB,CAAC;CAChC,MAAM,QAAqB,CAAC;CAE5B,KAAK,MAAM,CAAC,MAAM,QAAQ,OAAO,QAAQ,SAAS,MAAM,GAAG;EACzD,MAAM,QAAQ,oBAAoB,IAAIA,mBAAiB,IAAI,CAAC;EAC5D,IAAI,CAAC,OAAO;GACV,MAAM,KAAK;IAAE,cAAc;IAAM,QAAQ;GAAmB,CAAC;GAC7D;EACF;EAEA,MAAM,QAAQ,gBAAgB,GAAG;EACjC,MAAM,EAAE,QAAQ,YAAY,MAAM,UAAU,MAAM,UAAU,OAAO,MAAM;EAEzE,QAAQ,KAAK;GACX,WAAW,MAAM;GACjB,cAAc;GACd,UAAU,MAAM;GAChB;GACA;EACF,CAAC;CACH;CAEA,OAAO;EAAE;EAAS;CAAM;AAC1B;;;;;;AAOA,SAAgB,gBAAgB,KAA+B;CAC7D,MAAM,QAAkB;EACtB;EACA;EACA;EACA;EACA;CACF;CACA,MAAM,QAAkB,CAAC;CACzB,MAAM,KAAK,eAAe,IAAI,cAAc,eAAe,EAAE,QAAQ;CACrE,MAAM,KAAK,kBAAkB,gBAAgB,IAAI,QAAQ,GAAG;CAC5D,IAAI,IAAI,UAAU,MAAM,KAAK,iBAAiB,IAAI,UAAU;CAC5D,IAAI,IAAI,SAAS,MAAM,KAAK,kBAAkB,IAAI,QAAQ,GAAG;CAC7D,MAAM,KAAK,MAAM,KAAK,KAAK,CAAC;CAC5B,IAAI,IAAI,WAAW,SAAS,GAAG;EAC7B,MAAM,KAAK,EAAE;EACb,MAAM,KACJ,6BAA6B,IAAI,WAAW,KAAK,MAAM,KAAK,EAAE,GAAG,CAAC,CAAC,KAAK,IAAI,GAC9E;CACF;CACA,IAAI,IAAI,eAAe,SAAS,GAAG;EACjC,MAAM,KAAK,EAAE;EACb,MAAM,KACJ,sBAAsB,IAAI,eAAe,KAAK,MAAM,KAAK,EAAE,GAAG,CAAC,CAAC,KAAK,IAAI,GAC3E;CACF;CACA,MAAM,KAAK,UAAU,IAAI,SAAS;CAElC,OAAO,MAAM,KAAK,IAAI;AACxB;AAEA,eAAe,UACb,UACA,OACA,QAC6D;CAC7D,MAAM,UAAU,MAAM,SAAS,UAAU,MAAM;CAE/C,MAAM,WAAW,QAAQ,QAAQ,WAAW;CAC5C,MAAM,SAAS,QAAQ,QAAQ,SAAS;CAExC,IAAI;CACJ,IAAI;CAEJ,IAAI,aAAa,MAAM,SAAS,UAAU;EAExC,MAAM,SAAS,QAAQ,MAAM,GAAG,QAAQ;EACxC,MAAM,QAAQ,QAAQ,MAAM,SAAS,EAAgB;EACrD,OAAO,SAAS,QAAQ;EACxB,SAAS;CACX,OAAO;EAEL,MAAM,YAAY,QAAQ,OAAO,eAAe;EAChD,MAAM,YAAY,SAAS,QAAQ;EACnC,OACE,aAAa,IACT,QAAQ,MAAM,GAAG,SAAS,IAC1B,YACA,OACA,QAAQ,MAAM,SAAS,IACvB,QAAQ,QAAQ,QAAQ,EAAE,IAAI;EACpC,SAAS;CACX;CAEA,MAAM,UAAU,SAAS;CACzB,IAAI,CAAC,UAAU,SACb,MAAM,UAAU,UAAU,MAAM,MAAM;CAExC,OAAO;EAAE;EAAQ;CAAQ;AAC3B;;AAGA,MAAa,qBACX;AAuBF,SAAgB,kBACd,QACA,QACc;CACd,MAAM,UAAU,OAAO,QAAQ,QAAQ,MAAM,EAAE,WAAW,QAAQ,CAAC,CAAC;CACpE,MAAM,WAAW,OAAO,QAAQ,QAAQ,MAAM,EAAE,WAAW,SAAS,CAAC,CAAC;CACtE,MAAM,eAAe,OAAO,QAAQ,QAAQ,MAAM,EAAE,OAAO,CAAC,CAAC;CAC7D,OAAO;EACL,MAAM;EACN;EACA,WAAW,OAAO,QAAQ,SAAS,OAAO,MAAM;EAChD,SAAS,OAAO,MAAM;EACtB;EACA;EACA;EACA,YAAY,eAAe;CAC7B;AACF;AAEA,SAASA,mBAAiB,IAAoB;CAC5C,OAAO,GAAG,YAAY,CAAC,CAAC,WAAW,aAAa,EAAE;AACpD;AAEA,SAAS,gBAAgB,KAAqB;CAE5C,MAAM,IAAI,IAAI,KAAK,GAAG;CACtB,MAAM,OAAO,MAAc,OAAO,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;CACpD,OACE,GAAG,EAAE,eAAe,EAAE,GAAG,IAAI,EAAE,YAAY,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,WAAW,CAAC,EAAE,GACtE,IAAI,EAAE,YAAY,CAAC,EAAE,GAAG,IAAI,EAAE,cAAc,CAAC,EAAE;AAEtD;;;;AC7MA,MAAa,wBACX;AAmEF,MAAM,kBAAkB;AAExB,eAAsB,4BACpB,MACyB;CACzB,MAAM,EACJ,UACA,aACA,SAAS,OACT,YAAY,OACZ,SAAS,kBAAkB,oBACzB;CACJ,MAAM,MAAM,MAAM,WAAW;CAC7B,MAAM,QAAQ,MAAM,iBAAiB,WAAW;CAEhD,MAAM,aAAoC,CAAC;CAE3C,MAAM,aAAa,gBAAgB,QAAQ;CAC3C,MAAM,aAAa,gBAAgB,QAAQ;CAE3C,MAAM,gBAAgB,IAAI,IAAI,MAAM,SAAS,KAAK,CAAC;CACnD,MAAM,gBAAgB,IAAI,IAAI,MAAM,SAAS,KAAK,CAAC;CACnD,MAAM,cAAc,IAAI,IACtB,CAAC,GAAG,MAAM,OAAO,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,OAAO,CAC3C,iBAAiB,EAAE,GACnB;EAAE;EAAI,SAAS,EAAE,WAAW;CAAgB,CAC9C,CAAC,CACH;CAEA,IAAI,CAAC,WAAW;EACd,KAAK,MAAM,aAAa,YAAY;GAClC,IAAI,cAAc,IAAI,SAAS,GAAG;IAChC,WAAW,KAAK;KAAE,MAAM;KAAW,IAAI;KAAW,QAAQ;IAAS,CAAC;IACpE;GACF;GACA,WAAW,KAAK;IACd,MAAM;IACN,IAAI;IACJ,QAAQ,SAAS,iBAAiB;GACpC,CAAC;GACD,IAAI,CAAC,QACH,MAAM,IAAI,aAAa;IACrB,IAAI;IACJ,MAAM;IACN,SAAS;IACT,SAAS,oCAAoC,SAAS,YAAY;IAClE,UAAU,qBAAqB,WAAW,QAAQ;GACpD,CAAC;GAEH,cAAc,IAAI,SAAS;EAC7B;EAEA,KAAK,MAAM,aAAa,YAAY;GAClC,IAAI,cAAc,IAAI,SAAS,GAAG;IAChC,WAAW,KAAK;KAAE,MAAM;KAAW,IAAI;KAAW,QAAQ;IAAS,CAAC;IACpE;GACF;GACA,WAAW,KAAK;IACd,MAAM;IACN,IAAI;IACJ,QAAQ,SAAS,iBAAiB;GACpC,CAAC;GACD,IAAI,CAAC,QACH,MAAM,IAAI,aAAa;IACrB,IAAI;IACJ,MAAM;IACN,SAAS;IACT,SAAS,oCAAoC,SAAS,YAAY;IAClE,SAAS;IACT,WAAW,CAAC,OAAO;IACnB,UAAU,qBAAqB,WAAW,QAAQ;GACpD,CAAC;GAEH,cAAc,IAAI,SAAS;EAC7B;EAEA,KAAK,MAAM,CAAC,cAAc,QAAQ,OAAO,QAAQ,SAAS,MAAM,GAAG;GACjE,MAAM,aAAa,iBAAiB,YAAY;GAChD,MAAM,WAAW,YAAY,IAAI,UAAU;GAC3C,IAAI,UAAU;IACZ,WAAW,KAAK;KACd,MAAM;KACN,IAAI,SAAS;KACb,QAAQ;KACR,QAAQ;IACV,CAAC;IACD;GACF;GAEA,MAAM,UAAU,iBAAiB,YAAY;GAC7C,MAAM,WAAW,IAAI,QAAQ;GAC7B,MAAM,UACH,YAAY,OAAO,aAAa,WAC5B,WACD,WAAc,+BAA+B,GAAG;GACtD,MAAM,eAAe,WAAW,aAAa;GAC7C,WAAW,KAAK;IACd,MAAM;IACN,IAAI;IACJ,QAAQ,SAAS,iBAAiB;IAClC,QAAQ;IACR;GACF,CAAC;GACD,IAAI,CAAC,QAAQ;IACX,MAAM,IAAI,WAAW;KACnB,IAAI;KACJ,MAAM;KACN,SAAS;KACT,SAAS,0CAA0C,aAAa;KAChE,YAAY;KACZ,UAAU,mBAAmB,cAAc,KAAK,YAAY;KAO5D,GAAI,IAAI,UACJ,EAAE,UAAU,CAAC;MAAE,IAAI,IAAI;MAAS,SAAS;KAAgB,CAAC,EAAE,IAC5D,CAAC;IACP,CAAC;IACD,MAAM,IAAI,iBAAiB,SAAS;KAClC,QAAQ,KAAK,UAAU,QAAQ,MAAM,CAAC;KACtC,UAAU;IACZ,CAAC;GACH;GACA,YAAY,IAAI,YAAY;IAAE,IAAI;IAAS,SAAS;GAAgB,CAAC;EACvE;CACF;CAGA,KAAK,MAAM,CAAC,cAAc,QAAQ,OAAO,QAAQ,SAAS,MAAM,GAAG;EACjE,MAAM,QAAQ,YAAY,IAAI,iBAAiB,YAAY,CAAC;EAC5D,IAAI,CAAC,OAAO;EACZ,IAAI,IAAI,UAAU;GAChB,WAAW,KAAK;IACd,MAAM;IACN,IAAI,GAAG,IAAI,SAAS,IAAI,MAAM;IAC9B,QAAQ,SAAS,eAAe;GAClC,CAAC;GACD,IAAI,CAAC,QACH,MAAM,IAAI,kBAAkB,IAAI,UAAU,SAAS;IACjD,IAAI,MAAM;IACV,SAAS,MAAM,WAAW;GAC5B,CAAC;EAEL;EACA,KAAK,MAAM,YAAY,IAAI,aAAa,CAAC,GAAG;GAC1C,WAAW,KAAK;IACd,MAAM;IACN,IAAI,GAAG,SAAS,IAAI,MAAM;IAC1B,QAAQ,SAAS,eAAe;IAChC,QAAQ;GACV,CAAC;GACD,IAAI,CAAC,QACH,MAAM,IAAI,kBAAkB,UAAU,YAAY;IAChD,IAAI,MAAM;IACV,SAAS,MAAM,WAAW;GAC5B,CAAC;EAEL;EACA,IAAI,IAAI,SACN,WAAW,KAAK;GACd,MAAM;GACN,IAAI,GAAG,MAAM,GAAG,IAAI,IAAI;GACxB,QAAQ,SAAS,eAAe;EAClC,CAAC;CAKL;CAEA,OAAO,EAAE,WAAW;AACtB;AAEA,SAAgB,qBACd,QACA,SACiB;CACjB,MAAM,YAAY,OAChB,GAAG,WAAW,YAAY,GAAG,WAAW;CAC1C,MAAM,UAAU,OACd,GAAG,WAAW,UAAU,GAAG,WAAW;CAExC,MAAM,UAAU;EACd,UAAU,OAAO,WACd,QAAQ,MAAM,EAAE,SAAS,aAAa,SAAS,CAAC,CAAC,CAAC,CAClD,KAAK,MAAM,EAAE,EAAE;EAClB,QAAQ,OAAO,WACZ,QAAQ,MAAM,EAAE,SAAS,WAAW,SAAS,CAAC,CAAC,CAAC,CAChD,KAAK,MAAM,EAAE,EAAE;EAClB,UAAU,OAAO,WACd,QAAQ,MAAM,EAAE,SAAS,aAAa,SAAS,CAAC,CAAC,CAAC,CAClD,KAAK,MAAM,EAAE,EAAE;CACpB;CAEA,MAAM,QAA8C,CAAC;CACrD,MAAM,WAAiD,CAAC;CACxD,MAAM,WAAiD,CAAC;CACxD,KAAK,MAAM,MAAM,OAAO,YAAY;EAClC,IAAI,CAAC,OAAO,EAAE,GAAG;EACjB,IAAI,GAAG,SAAS,gBACd,IAAI,GAAG,WAAW,YAAY;GAC5B,MAAM,CAAC,SAAS,SAAS,GAAG,GAAG,MAAM,IAAI;GACzC,IAAI,WAAW,OAAO,SAAS,KAAK;IAAE;IAAS;GAAM,CAAC;EACxD,OAAO;GACL,MAAM,CAAC,SAAS,SAAS,GAAG,GAAG,MAAM,IAAI;GACzC,IAAI,WAAW,OAAO,MAAM,KAAK;IAAE;IAAS;GAAM,CAAC;EACrD;OACK,IAAI,GAAG,SAAS,gBAAgB;GACrC,MAAM,CAAC,OAAO,WAAW,GAAG,GAAG,MAAM,IAAI;GACzC,IAAI,SAAS,SAAS,SAAS,KAAK;IAAE;IAAS;GAAM,CAAC;EACxD;CACF;CAEA,MAAM,gBAAgB;EACpB,UAAU,OAAO,WAAW,QACzB,MAAM,EAAE,SAAS,WAAW,EAAE,iBAAiB,UAClD,CAAC,CAAC;EACF,UAAU,OAAO,WAAW,QACzB,MAAM,EAAE,SAAS,WAAW,EAAE,iBAAiB,UAClD,CAAC,CAAC;CACJ;CAEA,MAAM,UAAU;EACd,UAAU,OAAO,WACd,QAAQ,MAAM,EAAE,SAAS,aAAa,EAAE,WAAW,QAAQ,CAAC,CAC5D,KAAK,MAAM,EAAE,EAAE;EAClB,QAAQ,OAAO,WACZ,QAAQ,MAAM,EAAE,SAAS,WAAW,EAAE,WAAW,QAAQ,CAAC,CAC1D,KAAK,MAAM,EAAE,EAAE;EAClB,UAAU,OAAO,WACd,QAAQ,MAAM,EAAE,SAAS,aAAa,EAAE,WAAW,QAAQ,CAAC,CAC5D,KAAK,MAAM,EAAE,EAAE;CACpB;CAEA,MAAM,eACJ,QAAQ,SAAS,SAAS,QAAQ,OAAO,SAAS,QAAQ,SAAS;CACrE,MAAM,cAAc,MAAM,SAAS,SAAS,SAAS,SAAS;CAC9D,MAAM,eACJ,QAAQ,SAAS,SAAS,QAAQ,OAAO,SAAS,QAAQ,SAAS;CAErE,OAAO;EACL,MAAM;EACN,QAAQ,QAAQ;EAChB,WAAW,QAAQ;EACnB,WAAW,OAAO,WAAW;EAC7B,QAAQ;GACN,SAAS;GACT,QAAQ;GACR,SAAS;EACX;EACA;EACA,OAAO;GAAE;GAAO;GAAU;EAAS;EACnC;EACA;CACF;AACF;AAEA,SAAgB,+BACd,aACyB;CACzB,MAAM,OAAgC;EACpC,SAAS;EACT,MAAM;EACN,YAAY,CAAC;CACf;CAEA,MAAM,QAAQ,IAAI,IAAY,YAAY,UAAU;CACpD,KAAK,MAAM,QAAQ,OAAO,KAAK,YAAY,cAAc,CAAC,CAAC,GACzD,MAAM,IAAI,IAAI;CAGhB,MAAM,SAAS,CAAC,GAAG,KAAK,CAAC,CAAC,SAAS;CACnC,MAAM,QAAQ,YAAY,cAAc,CAAC;CACzC,KAAK,MAAM,QAAQ,QACjB,iBAAiB,MAAM,MAAM,MAAM,KAAK,EAAE,SAAS,CAAC,CAAC;CAEvD,OAAO;AACT;AAEA,SAAS,iBACP,MACA,MACA,eACM;CACN,IAAI,CAAC,MAAM;CACX,MAAM,QAAQ,UAAU,IAAI;CAC5B,IAAI,UAAU;CAEd,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;EACrC,MAAM,OAAO,MAAM;EACnB,MAAM,OAAO,MAAM,MAAM,SAAS;EAElC,IAAI,CAAC,QAAQ,cAAc,OAAO,QAAQ,eAAe,UACvD,QAAQ,aAAa,CAAC;EAExB,MAAM,aAAa,QAAQ;EAC3B,MAAM,OACH,WAAW,KAAK,QAAgD,CAAC;EACpE,WAAW,KAAK,OAAO;EAEvB,IAAI,KAAK,OAAO;GACd,KAAK,OAAO;GACZ,MAAM,QACH,KAAK,SACL,CAAC;GACJ,KAAK,QAAQ;GACb,IAAI,CAAC,SAAS,CAAC,MAAM,QAAQ,MAAM,SAAS,UAC1C,MAAM,OAAO;GAEf,UAAU;EACZ,OAAO;GACL,IAAI,QAAQ,cAAc,SAAS,GACjC,QAAQ,MAAM,aAAa;QAE3B,IAAI,CAAC,KAAK,QAAQ,KAAK,SAAS,SAAS,KAAK,OAAO;GAEvD,UAAU;EACZ;CACF;AACF;AAEA,SAAS,QAAQ,YAAqC,OAAuB;CAC3E,MAAM,SAAS,gBAAgB,KAAK;CACpC,IAAI,OAAO,WAAW,GACpB,WAAW,OAAO,OAAO;MACpB,IAAI,OAAO,SAAS,GACzB,WAAW,OAAO;AAEtB;AAEA,SAAS,gBAAgB,OAA2B;CAClD,MAAM,sBAAM,IAAI,IAAY;CAC5B,KAAK,MAAM,KAAK,OACd,QAAQ,GAAR;EACE,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;GACH,IAAI,IAAI,CAAC;GACT;EACF,SACE;CACJ;CAEF,OAAO,CAAC,GAAG,GAAG;AAChB;AAEA,SAAS,UAAU,MAAsD;CACvE,MAAM,WAAW,KAAK,MAAM,GAAG;CAC/B,MAAM,MAA8C,CAAC;CACrD,KAAK,MAAM,WAAW,UAAU;EAC9B,MAAM,UAAU,QAAQ,SAAS,IAAI;EACrC,IAAI,KAAK;GACP,KAAK,UAAU,QAAQ,MAAM,GAAG,EAAE,IAAI;GACtC,OAAO;EACT,CAAC;CACH;CACA,OAAO;AACT;AAEA,SAAS,gBAAgB,UAA6C;CACpE,MAAM,sBAAM,IAAI,IAAY;CAC5B,KAAK,MAAM,OAAO,OAAO,OAAO,SAAS,MAAM,GAAG;EAChD,IAAI,IAAI,UAAU,IAAI,IAAI,IAAI,QAAQ;EACtC,KAAK,MAAM,YAAY,IAAI,aAAa,CAAC,GAAG,IAAI,IAAI,QAAQ;CAC9D;CACA,OAAO;AACT;AAEA,SAAS,gBAAgB,UAA6C;CACpE,MAAM,sBAAM,IAAI,IAAY;CAC5B,KAAK,MAAM,OAAO,OAAO,OAAO,SAAS,MAAM,GAC7C,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,OAAO;CAEtC,OAAO;AACT;AAIA,MAAM,qBAAqB;;AAG3B,SAAS,mBACP,cACA,KACA,cACQ;CACR,MAAM,YAAY,IAAI,eAAe,KACjC,qBAAqB,IAAI,eAAe,GAAG,QAC3C;CACJ,MAAM,eAAe,IAAI,WAAW,iBAAiB,IAAI,SAAS,QAAQ;CAC1E,MAAM,cAAc,IAAI,UAAU,gBAAgB,IAAI,QAAQ,QAAQ;CACtE,MAAM,aACJ,iBAAiB,aACb,+DACA;CAEN,OAAO,GAAG,mBAAmB;;KAE1B,aAAa;;;;;eAKH,IAAI,cAAc,SAAS,IAAI,kBAAkB,IAAI,KAAK,IAAI;kBAC3D,IAAI,UAAU;iBACf,IAAI,SAAS;EAC5B,eAAe,cAAc,YAAY,WAAW;;AAEtD;AAEA,SAAS,qBACP,WACA,UACQ;CACR,MAAM,QAAQ,OAAO,QAAQ,SAAS,MAAM,CAAC,CAC1C,QAAQ,GAAG,SAAS,IAAI,aAAa,SAAS,CAAC,CAC/C,KAAK,CAAC,UAAU,OAAO,KAAK,GAAG,CAAC,CAChC,KAAK,IAAI;CACZ,MAAM,aAAa,QAAQ,cAAc,MAAM,MAAM;CAErD,OAAO,GAAG,mBAAmB;;KAE1B,UAAU;;;;EAIb;AACF;AAEA,SAAS,qBACP,WACA,UACQ;CACR,MAAM,WAAW,OAAO,QAAQ,SAAS,MAAM,CAAC,CAC7C,QAAQ,GAAG,SAAS,IAAI,YAAY,SAAS,CAAC,CAC9C,KAAK,CAAC,UAAU,OAAO,KAAK,GAAG,CAAC,CAChC,KAAK,IAAI;CACZ,MAAM,gBAAgB,WAAW,gBAAgB,SAAS,MAAM;CAEhE,OAAO,GAAG,mBAAmB;;KAE1B,UAAU;;;;EAIb;AACF;AAEA,SAAS,iBAAiB,mBAAmC;CAC3D,OAAO,kBACJ,MAAM,WAAW,CAAC,CAClB,OAAO,OAAO,CAAC,CACf,KAAK,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,YAAY,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAC3D,KAAK,EAAE;AACZ;AAEA,SAAS,iBAAiB,IAAoB;CAC5C,OAAO,GAAG,YAAY,CAAC,CAAC,WAAW,aAAa,EAAE;AACpD"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/snapshot.ts","../src/catalog.ts","../src/diff.ts","../src/diff-vs-base.ts","../src/renderers/types.ts","../src/renderers/markdown.ts","../src/renderers/terminal.ts","../src/renderers/json.ts","../src/eventcatalog-snapshot-diff.ts","../src/renderers/eventcatalog-snapshot-diff.ts","../src/renderers/index.ts","../src/policy.ts","../src/stamp.ts","../src/generate.ts"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/snapshot.ts","../src/catalog.ts","../src/diff.ts","../src/diff-vs-base.ts","../src/renderers/types.ts","../src/renderers/markdown.ts","../src/renderers/terminal.ts","../src/renderers/json.ts","../src/eventcatalog-snapshot-diff.ts","../src/renderers/eventcatalog-snapshot-diff.ts","../src/renderers/index.ts","../src/policy.ts","../src/stamp.ts","../src/generate.ts"],"mappings":"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"}