@pattern-stack/codegen 0.27.2 → 0.28.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.
Files changed (50) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/dist/{chunk-YQA5PMOD.js → chunk-3GMQKHJD.js} +2 -2
  3. package/dist/{chunk-5TK7MEN4.js → chunk-CPUSJPAP.js} +1 -1
  4. package/dist/{chunk-5TK7MEN4.js.map → chunk-CPUSJPAP.js.map} +1 -1
  5. package/dist/{chunk-PBENHIN2.js → chunk-IB733A6R.js} +2 -2
  6. package/dist/{chunk-YHVZAL6U.js → chunk-K6LH4PXZ.js} +2 -2
  7. package/dist/{chunk-XW4XKN3F.js → chunk-KS4BZHIA.js} +7 -7
  8. package/dist/{chunk-BK5ICA2F.js → chunk-RUSUZZAF.js} +4 -4
  9. package/dist/{chunk-7LKAMLV4.js → chunk-T6SCOJF4.js} +4 -4
  10. package/dist/{chunk-LQZESSM3.js → chunk-WE6DIDMM.js} +1 -1
  11. package/dist/chunk-WE6DIDMM.js.map +1 -0
  12. package/dist/{chunk-K4BQQ2NN.js → chunk-YUVEJNRE.js} +133 -10
  13. package/dist/chunk-YUVEJNRE.js.map +1 -0
  14. package/dist/{chunk-EGXFEZ2N.js → chunk-Z7YFYK6H.js} +4 -4
  15. package/dist/runtime/subsystems/auth/auth.module.js +2 -2
  16. package/dist/runtime/subsystems/auth/index.js +11 -11
  17. package/dist/runtime/subsystems/bridge/bridge.module.js +6 -6
  18. package/dist/runtime/subsystems/bridge/index.js +6 -6
  19. package/dist/runtime/subsystems/events/events.module.js +3 -3
  20. package/dist/runtime/subsystems/events/generated/bus.js +2 -2
  21. package/dist/runtime/subsystems/events/generated/index.js +2 -2
  22. package/dist/runtime/subsystems/events/generated/registry.d.ts +6 -0
  23. package/dist/runtime/subsystems/events/generated/registry.js +1 -1
  24. package/dist/runtime/subsystems/events/index.js +3 -3
  25. package/dist/runtime/subsystems/index.js +34 -34
  26. package/dist/runtime/subsystems/integration/detection-config.schema.d.ts +6 -4
  27. package/dist/runtime/subsystems/integration/detection-config.schema.js +1 -1
  28. package/dist/runtime/subsystems/integration/index.js +1 -1
  29. package/dist/runtime/subsystems/jobs/index.js +13 -13
  30. package/dist/runtime/subsystems/jobs/job-worker.module.js +5 -5
  31. package/dist/runtime/subsystems/jobs/jobs-domain.module.js +3 -3
  32. package/dist/runtime/subsystems/observability/index.js +3 -3
  33. package/dist/runtime/subsystems/storage/index.js +4 -4
  34. package/dist/runtime/subsystems/storage/storage.module.js +2 -2
  35. package/dist/src/cli/index.js +81 -25
  36. package/dist/src/cli/index.js.map +1 -1
  37. package/dist/src/index.js +2 -2
  38. package/package.json +1 -1
  39. package/runtime/subsystems/events/generated/registry.ts +1 -0
  40. package/runtime/subsystems/integration/detection-config.schema.ts +7 -5
  41. package/templates/entity/new/clean-lite-ps/dto/output.ejs.t +6 -0
  42. package/dist/chunk-K4BQQ2NN.js.map +0 -1
  43. package/dist/chunk-LQZESSM3.js.map +0 -1
  44. /package/dist/{chunk-YQA5PMOD.js.map → chunk-3GMQKHJD.js.map} +0 -0
  45. /package/dist/{chunk-PBENHIN2.js.map → chunk-IB733A6R.js.map} +0 -0
  46. /package/dist/{chunk-YHVZAL6U.js.map → chunk-K6LH4PXZ.js.map} +0 -0
  47. /package/dist/{chunk-XW4XKN3F.js.map → chunk-KS4BZHIA.js.map} +0 -0
  48. /package/dist/{chunk-BK5ICA2F.js.map → chunk-RUSUZZAF.js.map} +0 -0
  49. /package/dist/{chunk-7LKAMLV4.js.map → chunk-T6SCOJF4.js.map} +0 -0
  50. /package/dist/{chunk-EGXFEZ2N.js.map → chunk-Z7YFYK6H.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/parser/load-entities.ts","../src/utils/find-yaml-files.ts","../src/utils/yaml-loader.ts","../src/schema/entity-definition.schema.ts","../src/schema/event-definition.schema.ts","../src/schema/relationship-definition.schema.ts","../src/schema/junction-definition.schema.ts","../src/patterns/library/base-junction-fields.ts","../src/schema/provider-definition.schema.ts","../src/schema/job-definition.schema.ts","../src/parser/entity-registry.ts","../src/parser/validate-providers.ts","../src/parser/load-jobs.ts","../src/analyzer/graph-builder.ts","../src/behaviors/external-id-tracking.ts","../src/behaviors/soft-delete.ts","../src/behaviors/timestamps.ts","../src/behaviors/user-tracking.ts","../src/behaviors/index.ts","../src/analyzer/consistency-checker.ts","../src/analyzer/statistics.ts","../src/analyzer/transitive-suggester.ts","../src/analyzer/manifest.ts","../src/analyzer/serialize-graph.ts","../src/patterns/registry.ts","../src/patterns/pattern-definition.ts","../src/patterns/validate-composition.ts","../src/patterns/validate-orchestration.ts","../src/formatters/console-formatter.ts","../src/formatters/json-formatter.ts","../src/formatters/markdown-formatter.ts","../src/patterns/library/activity.pattern.ts","../src/patterns/library/base.pattern.ts","../src/patterns/library/junction.pattern.ts","../src/patterns/library/knowledge.pattern.ts","../src/patterns/library/metadata.pattern.ts","../src/patterns/library/integrated.pattern.ts","../src/patterns/library/index.ts","../src/emitters/frontend/field-meta.ts","../src/index.ts"],"sourcesContent":["/**\n * Entity Loader\n *\n * Loads and parses all YAML entity files from a directory.\n * Reuses existing yaml-loader and entity-definition schema from codegen.\n */\n\nimport { resolve } from 'node:path';\nimport { findYamlFiles } from '../utils/find-yaml-files';\nimport {\n\tloadEntityFromYaml,\n\tloadRelationshipFromYaml,\n\ttype LoadResult,\n\ttype LoadError,\n\ttype RelationshipLoadResult,\n\ttype RelationshipLoadError,\n} from '../utils/yaml-loader';\nimport type {\n\tParsedEntity,\n\tParsedEvent,\n\tParsedField,\n\tParsedProviderIntegration,\n\tParsedQuery,\n\tParsedRelationship,\n\tParsedRelationshipDefinition,\n\tParsedIntegration,\n\tParsedTypeDirection,\n\tAnalysisIssue,\n} from '../analyzer/types';\nimport {\n\tderiveRelationshipFKColumns,\n\tderiveTableName,\n\tderiveUniqueConstraint,\n\tcollectTypeNames,\n\ttype RelationshipDefinition,\n\ttype RelationshipTypes,\n} from '../schema/relationship-definition.schema';\nimport type { FieldDefinition } from '../schema/entity-definition.schema';\n\n/**\n * Map the YAML `ui_*` keys onto `ParsedField.ui`. Shared by the entity and\n * relationship-definition field parsers so the two cannot drift. Carries the\n * full UI-hint surface (label/type/importance/group/sortable/filterable/\n * visible/placeholder/help/format) plus key-field curation\n * (`ui_key_field` / `ui_key_field_order`, ADR-040).\n */\nfunction parseUiMetadata(fieldDef: FieldDefinition): ParsedField['ui'] {\n\treturn {\n\t\tlabel: fieldDef.ui_label,\n\t\ttype: fieldDef.ui_type,\n\t\timportance: fieldDef.ui_importance,\n\t\tgroup: fieldDef.ui_group,\n\t\tsortable: fieldDef.ui_sortable,\n\t\tfilterable: fieldDef.ui_filterable,\n\t\tvisible: fieldDef.ui_visible,\n\t\tplaceholder: fieldDef.ui_placeholder,\n\t\thelp: fieldDef.ui_help,\n\t\tformat: fieldDef.ui_format,\n\t\tkeyField: fieldDef.ui_key_field,\n\t\tkeyFieldOrder: fieldDef.ui_key_field_order,\n\t};\n}\n\nexport interface LoadEntitiesResult {\n\tentities: ParsedEntity[];\n\tissues: AnalysisIssue[];\n}\n\n/**\n * Transform a loaded entity definition into a ParsedEntity\n */\nfunction transformToEntity(result: LoadResult): ParsedEntity {\n\tconst { definition, filePath } = result;\n\n\t// Search queries use a different shape (name/filters/search/paginate) and\n\t// are consumed directly by the codegen templates, not by the analyzer.\n\t// Narrow to the by-column variant here for ParsedQuery mapping.\n\tconst queries: ParsedQuery[] | undefined = definition.queries\n\t\t?.filter((q): q is Extract<typeof q, { by: unknown }> => 'by' in q)\n\t\t.map((q) => ({\n\t\t\tby: q.by,\n\t\t\tunique: q.unique,\n\t\t\tselect: q.select,\n\t\t\torder: q.order,\n\t\t\tlimit: q.limit,\n\t\t\tvia: q.via,\n\t\t}));\n\n\tconst entity: ParsedEntity = {\n\t\tname: definition.entity.name,\n\t\tplural: definition.entity.plural,\n\t\ttable: definition.entity.table,\n\t\tpattern: definition.entity.pattern,\n\t\tpatterns: definition.entity.patterns,\n\t\tpatternConfig: definition.entity.config,\n\t\tscopeable: definition.entity.scopeable ?? false,\n\t\texpose: definition.entity.expose ?? ['repository', 'rest', 'trpc'],\n\t\tfolderStructure: definition.entity.folder_structure ?? 'nested',\n\t\tfields: new Map(),\n\t\trelationships: new Map(),\n\t\tbehaviors: definition.behaviors.map((b) => (typeof b === 'string' ? b : b.name)),\n\t\tqueries,\n\t\tsourcePath: filePath,\n\t};\n\n\t// Parse fields\n\tfor (const [name, fieldDef] of Object.entries(definition.fields)) {\n\t\tconst field: ParsedField = {\n\t\t\tname,\n\t\t\ttype: fieldDef.type,\n\t\t\trequired: fieldDef.required ?? false,\n\t\t\tnullable: fieldDef.nullable ?? false,\n\t\t\tunique: fieldDef.unique ?? false,\n\t\t\tindex: fieldDef.index ?? false,\n\t\t\tforeignKey: fieldDef.foreign_key ? parseForeignKey(fieldDef.foreign_key) : undefined,\n\t\t\tchoices: fieldDef.choices,\n\t\t\tconstraints: {\n\t\t\t\tminLength: fieldDef.min_length,\n\t\t\t\tmaxLength: fieldDef.max_length,\n\t\t\t\tmin: fieldDef.min,\n\t\t\t\tmax: fieldDef.max,\n\t\t\t},\n\t\t\tui: parseUiMetadata(fieldDef),\n\t\t};\n\t\tentity.fields.set(name, field);\n\t}\n\n\t// Parse relationships\n\tif (definition.relationships) {\n\t\tfor (const [name, relDef] of Object.entries(definition.relationships)) {\n\t\t\tconst relationship: ParsedRelationship = {\n\t\t\t\tname,\n\t\t\t\ttype: relDef.type,\n\t\t\t\ttarget: relDef.target,\n\t\t\t\tforeignKey: relDef.foreign_key,\n\t\t\t\tinverse: relDef.inverse,\n\t\t\t\tthrough: relDef.through,\n\t\t\t\tresolved: false,\n\t\t\t};\n\t\t\tentity.relationships.set(name, relationship);\n\t\t}\n\t}\n\n\t// Parse integration configuration\n\tif (definition.integration) {\n\t\tconst integrationDef = definition.integration;\n\t\tconst parsedIntegration: ParsedIntegration = {\n\t\t\telectric: integrationDef.electric ?? false,\n\t\t};\n\n\t\tif (integrationDef.providers) {\n\t\t\tparsedIntegration.providers = {};\n\t\t\tfor (const [providerName, providerDef] of Object.entries(integrationDef.providers)) {\n\t\t\t\tconst parsedProvider: ParsedProviderIntegration = {\n\t\t\t\t\tremoteEntity: providerDef.remote_entity,\n\t\t\t\t\tdirection: providerDef.direction,\n\t\t\t\t\tcdc: providerDef.cdc ?? false,\n\t\t\t\t};\n\t\t\t\tif (providerDef.field_mapping) {\n\t\t\t\t\tparsedProvider.fieldMapping = providerDef.field_mapping;\n\t\t\t\t}\n\t\t\t\tif (providerDef.read_only_fields) {\n\t\t\t\t\tparsedProvider.readOnlyFields = providerDef.read_only_fields;\n\t\t\t\t}\n\t\t\t\tparsedIntegration.providers[providerName] = parsedProvider;\n\t\t\t}\n\t\t}\n\n\t\tentity.integration = parsedIntegration;\n\t}\n\n\t// Parse events\n\tif (definition.events) {\n\t\tentity.events = definition.events.map((ev): ParsedEvent => ({\n\t\t\tname: ev.name,\n\t\t\tqueue: ev.queue,\n\t\t\tbody: ev.body,\n\t\t\tgenerateHandler: ev.generate_handler,\n\t\t}));\n\t}\n\n\t// Parse emits (EVT-7). Preserve `undefined` vs `[]` distinction — the\n\t// validator treats absence as a warning and explicit empty as opt-out.\n\tif (definition.emits !== undefined) {\n\t\tentity.emits = definition.emits;\n\t}\n\n\treturn entity;\n}\n\n/**\n * Parse a foreign key string (e.g., \"accounts.id\") into table and column\n */\nfunction parseForeignKey(fk: string): { table: string; column: string } {\n\tconst [table, column] = fk.split('.');\n\treturn { table, column: column ?? 'id' };\n}\n\n/**\n * Convert a load error to an analysis issue\n */\nfunction loadErrorToIssue(error: LoadError): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\tissues.push({\n\t\tseverity: 'error',\n\t\ttype: 'parse_error',\n\t\tmessage: error.error,\n\t\tpath: error.filePath,\n\t});\n\n\tif (error.details) {\n\t\tfor (const detail of error.details) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'error',\n\t\t\t\ttype: 'schema_error',\n\t\t\t\tmessage: detail,\n\t\t\t\tpath: error.filePath,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n/**\n * Load all entity YAML files from a directory\n */\nexport function loadEntities(\n\tentitiesDir: string,\n\topts?: { excludeDirs?: string[] },\n): LoadEntitiesResult {\n\tconst entities: ParsedEntity[] = [];\n\tconst issues: AnalysisIssue[] = [];\n\n\tconst resolvedDir = resolve(entitiesDir);\n\n\t// Get all YAML files. `excludeDirs` keeps the provider-definitions subtree\n\t// (`definitions/providers/*.yaml`) out — those validate against\n\t// ProviderDefinitionSchema, not the entity loader.\n\tlet files: string[];\n\ttry {\n\t\tfiles = findYamlFiles(resolvedDir, { excludeDirs: opts?.excludeDirs });\n\t} catch (err) {\n\t\tissues.push({\n\t\t\tseverity: 'error',\n\t\t\ttype: 'parse_error',\n\t\t\tmessage: `Failed to read directory: ${resolvedDir}`,\n\t\t\tpath: resolvedDir,\n\t\t});\n\t\treturn { entities, issues };\n\t}\n\n\tif (files.length === 0) {\n\t\tissues.push({\n\t\t\tseverity: 'warning',\n\t\t\ttype: 'no_files',\n\t\t\tmessage: `No YAML files found in directory: ${resolvedDir}`,\n\t\t\tpath: resolvedDir,\n\t\t});\n\t\treturn { entities, issues };\n\t}\n\n\t// Load each file\n\tfor (const filePath of files) {\n\t\tconst result = loadEntityFromYaml(filePath);\n\n\t\tif (result.success) {\n\t\t\tentities.push(transformToEntity(result));\n\t\t} else {\n\t\t\tissues.push(...loadErrorToIssue(result));\n\t\t}\n\t}\n\n\treturn { entities, issues };\n}\n\n/**\n * Resolve cross-entity references\n */\nexport function resolveReferences(entities: ParsedEntity[]): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\tconst entityMap = new Map<string, ParsedEntity>();\n\n\t// Build entity map by name\n\tfor (const entity of entities) {\n\t\tif (entityMap.has(entity.name)) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'error',\n\t\t\t\ttype: 'duplicate_entity',\n\t\t\t\tentity: entity.name,\n\t\t\t\tmessage: `Duplicate entity name: ${entity.name}`,\n\t\t\t\tpath: entity.sourcePath,\n\t\t\t});\n\t\t}\n\t\tentityMap.set(entity.name, entity);\n\t}\n\n\t// Resolve relationships\n\tfor (const entity of entities) {\n\t\tfor (const [relName, rel] of entity.relationships) {\n\t\t\tconst targetEntity = entityMap.get(rel.target);\n\t\t\tif (targetEntity) {\n\t\t\t\trel.resolved = true;\n\t\t\t} else {\n\t\t\t\tissues.push({\n\t\t\t\t\tseverity: 'error',\n\t\t\t\t\ttype: 'missing_target',\n\t\t\t\t\tentity: entity.name,\n\t\t\t\t\tfield: relName,\n\t\t\t\t\tmessage: `Relationship '${relName}' references unknown entity '${rel.target}'`,\n\t\t\t\t\tpath: entity.sourcePath,\n\t\t\t\t\tsuggestion: `Define entity '${rel.target}' or fix the target name`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Check foreign key references\n\t\tfor (const [fieldName, field] of entity.fields) {\n\t\t\tif (field.foreignKey) {\n\t\t\t\tconst targetTable = field.foreignKey.table;\n\t\t\t\tconst targetEntity = Array.from(entityMap.values()).find(\n\t\t\t\t\t(e) => e.table === targetTable\n\t\t\t\t);\n\t\t\t\tif (!targetEntity) {\n\t\t\t\t\tissues.push({\n\t\t\t\t\t\tseverity: 'warning',\n\t\t\t\t\t\ttype: 'missing_fk_target',\n\t\t\t\t\t\tentity: entity.name,\n\t\t\t\t\t\tfield: fieldName,\n\t\t\t\t\t\tmessage: `Foreign key references unknown table '${targetTable}'`,\n\t\t\t\t\t\tpath: entity.sourcePath,\n\t\t\t\t\t\tsuggestion: `Define entity with table '${targetTable}' or fix the foreign_key reference`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n// ============================================================================\n// Relationship Loading\n// ============================================================================\n\nexport interface LoadRelationshipsResult {\n\trelationships: ParsedRelationshipDefinition[];\n\tissues: AnalysisIssue[];\n}\n\n/**\n * Transform a loaded relationship definition into a ParsedRelationshipDefinition.\n *\n * This resolves all auto-generated fields: FK columns, type directions,\n * temporal/sourced fields, unique constraints.\n */\nfunction transformToRelationshipDefinition(\n\tresult: RelationshipLoadResult,\n): ParsedRelationshipDefinition {\n\tconst { definition, filePath } = result;\n\tconst config = definition.relationship;\n\n\tconst { fromColumn, toColumn } = deriveRelationshipFKColumns(config);\n\tconst table = deriveTableName(config);\n\tconst uniqueOn = deriveUniqueConstraint(config);\n\n\t// Resolve type directions\n\tconst types = resolveTypeDirections(config.types);\n\n\t// Parse custom fields\n\tconst fields = new Map<string, ParsedField>();\n\tif (definition.fields) {\n\t\tfor (const [name, fieldDef] of Object.entries(definition.fields)) {\n\t\t\tconst field: ParsedField = {\n\t\t\t\tname,\n\t\t\t\ttype: fieldDef.type,\n\t\t\t\trequired: fieldDef.required ?? false,\n\t\t\t\tnullable: fieldDef.nullable ?? false,\n\t\t\t\tunique: fieldDef.unique ?? false,\n\t\t\t\tindex: fieldDef.index ?? false,\n\t\t\t\tforeignKey: fieldDef.foreign_key\n\t\t\t\t\t? parseForeignKey(fieldDef.foreign_key)\n\t\t\t\t\t: undefined,\n\t\t\t\tchoices: fieldDef.choices,\n\t\t\t\tconstraints: {\n\t\t\t\t\tminLength: fieldDef.min_length,\n\t\t\t\t\tmaxLength: fieldDef.max_length,\n\t\t\t\t\tmin: fieldDef.min,\n\t\t\t\t\tmax: fieldDef.max,\n\t\t\t\t},\n\t\t\t\tui: parseUiMetadata(fieldDef),\n\t\t\t};\n\t\t\tfields.set(name, field);\n\t\t}\n\t}\n\n\t// Parse queries\n\t// Relationship queries here: same filtering rationale as entity queries.\n\tconst queries: ParsedQuery[] | undefined = definition.queries\n\t\t?.filter((q): q is Extract<typeof q, { by: unknown }> => 'by' in q)\n\t\t.map((q) => ({\n\t\t\tby: q.by,\n\t\t\tunique: q.unique,\n\t\t\tselect: q.select,\n\t\t\torder: q.order,\n\t\t\tlimit: q.limit,\n\t\t}));\n\n\treturn {\n\t\tname: config.name,\n\t\ttable,\n\t\tfrom: config.from,\n\t\tto: config.to,\n\t\tselfReferential: config.from === config.to,\n\t\tfromColumn,\n\t\ttoColumn,\n\t\ttypes,\n\t\thasTypes: types.length > 0,\n\t\ttemporal: config.temporal,\n\t\tsourced: config.sourced,\n\t\tonDeleteFrom: config.on_delete_from ?? 'restrict',\n\t\tonDeleteTo: config.on_delete_to ?? 'restrict',\n\t\tuniqueOn,\n\t\tfields,\n\t\tqueries,\n\t\tsourcePath: filePath,\n\t};\n}\n\n/**\n * Resolve type directions from the YAML types: block.\n *\n * Simple list → all directed, no inverses.\n * Object map → each type has explicit direction metadata.\n */\nfunction resolveTypeDirections(\n\ttypes: RelationshipTypes | undefined,\n): ParsedTypeDirection[] {\n\tif (!types) return [];\n\n\tif (Array.isArray(types)) {\n\t\t// Simple list: all directed from→to\n\t\treturn types.map((name) => ({\n\t\t\tname,\n\t\t\tbidirectional: false,\n\t\t\tdirected: true,\n\t\t}));\n\t}\n\n\t// Object map: resolve each type's direction\n\treturn Object.entries(types).map(([name, dir]) => {\n\t\tconst direction = dir as { inverse?: string; bidirectional?: boolean; directed?: boolean };\n\t\treturn {\n\t\t\tname,\n\t\t\tinverse: direction.inverse,\n\t\t\tbidirectional: direction.bidirectional ?? false,\n\t\t\tdirected: direction.directed ?? (!direction.bidirectional && !direction.inverse),\n\t\t};\n\t});\n}\n\n/**\n * Load all relationship YAML files from a directory\n */\nexport function loadRelationships(\n\trelationshipsDir: string,\n): LoadRelationshipsResult {\n\tconst relationships: ParsedRelationshipDefinition[] = [];\n\tconst issues: AnalysisIssue[] = [];\n\n\tconst resolvedDir = resolve(relationshipsDir);\n\n\tlet files: string[];\n\ttry {\n\t\tfiles = findYamlFiles(resolvedDir);\n\t} catch {\n\t\t// Directory doesn't exist — not an error, relationships are optional\n\t\treturn { relationships, issues };\n\t}\n\n\tif (files.length === 0) {\n\t\treturn { relationships, issues };\n\t}\n\n\tfor (const filePath of files) {\n\t\tconst result = loadRelationshipFromYaml(filePath);\n\n\t\tif (result.success) {\n\t\t\trelationships.push(transformToRelationshipDefinition(result));\n\t\t} else {\n\t\t\tissues.push(...loadErrorToIssue(result as unknown as LoadError));\n\t\t}\n\t}\n\n\treturn { relationships, issues };\n}\n\n/**\n * Resolve cross-references between relationship definitions and entities.\n * Validates that from/to entities exist.\n */\nexport function resolveRelationshipReferences(\n\trelationshipDefs: ParsedRelationshipDefinition[],\n\tentities: ParsedEntity[],\n): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\tconst entityNames = new Set(entities.map((e) => e.name));\n\n\tfor (const relDef of relationshipDefs) {\n\t\tif (!entityNames.has(relDef.from)) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'warning',\n\t\t\t\ttype: 'missing_relationship_endpoint',\n\t\t\t\tentity: relDef.name,\n\t\t\t\tmessage: `Relationship '${relDef.name}' references unknown 'from' entity '${relDef.from}'`,\n\t\t\t\tpath: relDef.sourcePath,\n\t\t\t\tsuggestion: `Define entity '${relDef.from}' or fix the 'from' value`,\n\t\t\t});\n\t\t}\n\n\t\tif (!entityNames.has(relDef.to)) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'warning',\n\t\t\t\ttype: 'missing_relationship_endpoint',\n\t\t\t\tentity: relDef.name,\n\t\t\t\tmessage: `Relationship '${relDef.name}' references unknown 'to' entity '${relDef.to}'`,\n\t\t\t\tpath: relDef.sourcePath,\n\t\t\t\tsuggestion: `Define entity '${relDef.to}' or fix the 'to' value`,\n\t\t\t});\n\t\t}\n\n\t\t// Check for duplicate relationship names\n\t\tconst dupes = relationshipDefs.filter((r) => r.name === relDef.name);\n\t\tif (dupes.length > 1) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'error',\n\t\t\t\ttype: 'duplicate_relationship',\n\t\t\t\tentity: relDef.name,\n\t\t\t\tmessage: `Duplicate relationship name: ${relDef.name}`,\n\t\t\t\tpath: relDef.sourcePath,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn issues;\n}\n\nexport { loadEntityFromYaml } from '../utils/yaml-loader';\nexport { loadRelationshipFromYaml } from '../utils/yaml-loader';\nexport { loadJunctionFromYaml } from '../utils/yaml-loader';\n","/**\n * Recursive YAML discovery — the single source of truth for finding entity,\n * relationship, junction, and event definition files on disk.\n *\n * Domain-folder layouts are first-class: `entities/crm/account.yaml`,\n * `entities/billing/invoice.yaml`, and a flat `entities/account.yaml` are all\n * discovered identically. Every codegen discovery site routes through this\n * helper so the tree-walk behaviour stays consistent — there is no flat-vs-deep\n * split to keep in sync.\n *\n * `.yaml` and `.yml` are both matched. Dot-directories (`.git`, `.cache`, …)\n * are skipped so a stray VCS or tooling folder under the definitions root can\n * never be mistaken for a domain folder. Results are returned as absolute paths\n * sorted lexicographically for deterministic generation order.\n *\n * Throws if `dir` does not exist — matching `readdirSync` semantics so callers\n * can distinguish \"directory missing\" (catch → warn/skip) from \"directory\n * present but empty\" (empty array). Callers that treat a missing directory as\n * non-fatal should guard with `existsSync` or wrap in try/catch, exactly as\n * they did around the previous flat `readdirSync` calls.\n */\n\nimport { readdirSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\n\nfunction isYaml(name: string): boolean {\n\treturn name.endsWith('.yaml') || name.endsWith('.yml');\n}\n\n/**\n * Recursively collect every `.yaml`/`.yml` file under `dir`.\n *\n * @param dir Directory to walk (relative paths are resolved against cwd).\n * @param opts.excludeDirs Absolute directory paths to skip entirely (and their\n * subtrees). Used by entity discovery to keep `definitions/providers/*.yaml`\n * out of the entity glob — provider files validate against\n * `ProviderDefinitionSchema`, not `EntityDefinitionSchema`, so they must never\n * reach the entity loader. Paths are compared after `resolve`.\n * @returns Absolute file paths, sorted lexicographically. Throws if `dir`\n * does not exist.\n */\nexport function findYamlFiles(\n\tdir: string,\n\topts?: { excludeDirs?: string[] },\n): string[] {\n\tconst root = resolve(dir);\n\tconst out: string[] = [];\n\tconst excluded = new Set((opts?.excludeDirs ?? []).map((d) => resolve(d)));\n\n\tconst walk = (current: string): void => {\n\t\tfor (const entry of readdirSync(current, { withFileTypes: true })) {\n\t\t\tif (entry.isDirectory()) {\n\t\t\t\tif (entry.name.startsWith('.')) continue;\n\t\t\t\tconst child = join(current, entry.name);\n\t\t\t\tif (excluded.has(resolve(child))) continue;\n\t\t\t\twalk(child);\n\t\t\t} else if (isYaml(entry.name)) {\n\t\t\t\tout.push(join(current, entry.name));\n\t\t\t}\n\t\t}\n\t};\n\n\twalk(root);\n\treturn out.sort();\n}\n","import { readFileSync, existsSync } from 'node:fs';\nimport { parse as parseYaml } from 'yaml';\nimport { ZodError } from 'zod';\nimport {\n\ttype EntityDefinition,\n\tEntityDefinitionSchema,\n} from '../schema/entity-definition.schema';\nimport {\n\ttype EventDefinition,\n\tEventDefinitionSchema,\n} from '../schema/event-definition.schema';\nimport {\n\ttype RelationshipDefinition,\n\tRelationshipDefinitionSchema,\n} from '../schema/relationship-definition.schema';\nimport {\n\ttype JunctionDefinition,\n\tJunctionDefinitionSchema,\n} from '../schema/junction-definition.schema';\nimport {\n\ttype ProviderDefinition,\n\tProviderDefinitionSchema,\n} from '../schema/provider-definition.schema';\nimport {\n\ttype JobDefinition,\n\tJobDefinitionSchema,\n} from '../schema/job-definition.schema';\n\nexport interface LoadResult {\n\tsuccess: true;\n\tdefinition: EntityDefinition;\n\tfilePath: string;\n}\n\nexport interface LoadError {\n\tsuccess: false;\n\terror: string;\n\tdetails?: string[];\n\tfilePath: string;\n}\n\nexport type LoadEntityResult = LoadResult | LoadError;\n\n/**\n * Load and validate an entity definition from a YAML file\n */\nexport function loadEntityFromYaml(filePath: string): LoadEntityResult {\n\t// Check file exists\n\tif (!existsSync(filePath)) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `File not found: ${filePath}`,\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\t// Read file\n\tlet content: string;\n\ttry {\n\t\tcontent = readFileSync(filePath, 'utf-8');\n\t} catch (err) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Failed to read file: ${filePath}`,\n\t\t\tdetails: [err instanceof Error ? err.message : String(err)],\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\t// Parse YAML\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = parseYaml(content);\n\t} catch (err) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Invalid YAML syntax in ${filePath}`,\n\t\t\tdetails: [err instanceof Error ? err.message : String(err)],\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\t// Validate against schema\n\tconst result = EntityDefinitionSchema.safeParse(parsed);\n\tif (!result.success) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Validation failed for ${filePath}`,\n\t\t\tdetails: formatZodErrors(result.error),\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\treturn {\n\t\tsuccess: true,\n\t\tdefinition: result.data,\n\t\tfilePath,\n\t};\n}\n\n/**\n * Format Zod errors into human-readable messages\n */\nfunction formatZodErrors(error: ZodError): string[] {\n\treturn error.errors.map((err) => {\n\t\tconst path = err.path.join('.');\n\t\tconst location = path ? `at '${path}'` : 'at root';\n\t\treturn `${err.message} ${location}`;\n\t});\n}\n\n/**\n * Pretty-print a load error for CLI output\n */\nexport function formatLoadError(result: LoadError): string {\n\tconst lines = [`❌ ${result.error}`];\n\tif (result.details && result.details.length > 0) {\n\t\tlines.push('');\n\t\tfor (const detail of result.details) {\n\t\t\tlines.push(` • ${detail}`);\n\t\t}\n\t}\n\treturn lines.join('\\n');\n}\n\n/**\n * Load multiple entity files\n */\nexport function loadEntitiesFromYaml(filePaths: string[]): {\n\tsuccesses: LoadResult[];\n\tfailures: LoadError[];\n} {\n\tconst successes: LoadResult[] = [];\n\tconst failures: LoadError[] = [];\n\n\tfor (const filePath of filePaths) {\n\t\tconst result = loadEntityFromYaml(filePath);\n\t\tif (result.success) {\n\t\t\tsuccesses.push(result);\n\t\t} else {\n\t\t\tfailures.push(result);\n\t\t}\n\t}\n\n\treturn { successes, failures };\n}\n\n// ============================================================================\n// Relationship YAML Loading\n// ============================================================================\n\nexport interface RelationshipLoadResult {\n\tsuccess: true;\n\tdefinition: RelationshipDefinition;\n\tfilePath: string;\n}\n\nexport interface RelationshipLoadError {\n\tsuccess: false;\n\terror: string;\n\tdetails?: string[];\n\tfilePath: string;\n}\n\nexport type LoadRelationshipResult =\n\t| RelationshipLoadResult\n\t| RelationshipLoadError;\n\n/**\n * Load and validate a relationship definition from a YAML file\n */\nexport function loadRelationshipFromYaml(\n\tfilePath: string,\n): LoadRelationshipResult {\n\tif (!existsSync(filePath)) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `File not found: ${filePath}`,\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\tlet content: string;\n\ttry {\n\t\tcontent = readFileSync(filePath, 'utf-8');\n\t} catch (err) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Failed to read file: ${filePath}`,\n\t\t\tdetails: [err instanceof Error ? err.message : String(err)],\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = parseYaml(content);\n\t} catch (err) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Invalid YAML syntax in ${filePath}`,\n\t\t\tdetails: [err instanceof Error ? err.message : String(err)],\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\tconst result = RelationshipDefinitionSchema.safeParse(parsed);\n\tif (!result.success) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Validation failed for ${filePath}`,\n\t\t\tdetails: formatZodErrors(result.error),\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\treturn {\n\t\tsuccess: true,\n\t\tdefinition: result.data,\n\t\tfilePath,\n\t};\n}\n\n/**\n * Load multiple relationship files\n */\nexport function loadRelationshipsFromYaml(filePaths: string[]): {\n\tsuccesses: RelationshipLoadResult[];\n\tfailures: RelationshipLoadError[];\n} {\n\tconst successes: RelationshipLoadResult[] = [];\n\tconst failures: RelationshipLoadError[] = [];\n\n\tfor (const filePath of filePaths) {\n\t\tconst result = loadRelationshipFromYaml(filePath);\n\t\tif (result.success) {\n\t\t\tsuccesses.push(result);\n\t\t} else {\n\t\t\tfailures.push(result);\n\t\t}\n\t}\n\n\treturn { successes, failures };\n}\n\n// ============================================================================\n// Event YAML Loading\n// ============================================================================\n\nexport interface EventLoadResult {\n\tsuccess: true;\n\tdefinition: EventDefinition;\n\tfilePath: string;\n}\n\nexport interface EventLoadError {\n\tsuccess: false;\n\terror: string;\n\tdetails?: string[];\n\tfilePath: string;\n}\n\nexport type LoadEventResult = EventLoadResult | EventLoadError;\n\n/**\n * Load and validate a single event definition from a YAML file.\n *\n * Mirrors {@link loadEntityFromYaml}: existence check → readFileSync →\n * parseYaml → `EventDefinitionSchema.safeParse`. Returns a discriminated\n * result; callers are expected to aggregate into `AnalysisIssue`s rather\n * than throw.\n */\nexport function loadEventFromYaml(filePath: string): LoadEventResult {\n\tif (!existsSync(filePath)) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `File not found: ${filePath}`,\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\tlet content: string;\n\ttry {\n\t\tcontent = readFileSync(filePath, 'utf-8');\n\t} catch (err) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Failed to read file: ${filePath}`,\n\t\t\tdetails: [err instanceof Error ? err.message : String(err)],\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = parseYaml(content);\n\t} catch (err) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Invalid YAML syntax in ${filePath}`,\n\t\t\tdetails: [err instanceof Error ? err.message : String(err)],\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\tconst result = EventDefinitionSchema.safeParse(parsed);\n\tif (!result.success) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Validation failed for ${filePath}`,\n\t\t\tdetails: formatZodErrors(result.error),\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\treturn {\n\t\tsuccess: true,\n\t\tdefinition: result.data,\n\t\tfilePath,\n\t};\n}\n\n// ============================================================================\n// Job Definition YAML Loading (RFC-0005, breakdown #6)\n// ============================================================================\n\nexport interface JobLoadResult {\n\tsuccess: true;\n\tdefinition: JobDefinition;\n\tfilePath: string;\n}\n\nexport interface JobLoadError {\n\tsuccess: false;\n\terror: string;\n\tdetails?: string[];\n\tfilePath: string;\n}\n\nexport type LoadJobResult = JobLoadResult | JobLoadError;\n\n/**\n * Load and validate a single job definition from a YAML file.\n *\n * Mirrors {@link loadEventFromYaml}: existence check → readFileSync →\n * parseYaml → `JobDefinitionSchema.safeParse`. Returns a discriminated result;\n * callers (`loadJobs`) aggregate into `AnalysisIssue`s rather than throw.\n */\nexport function loadJobFromYaml(filePath: string): LoadJobResult {\n\tif (!existsSync(filePath)) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `File not found: ${filePath}`,\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\tlet content: string;\n\ttry {\n\t\tcontent = readFileSync(filePath, 'utf-8');\n\t} catch (err) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Failed to read file: ${filePath}`,\n\t\t\tdetails: [err instanceof Error ? err.message : String(err)],\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = parseYaml(content);\n\t} catch (err) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Invalid YAML syntax in ${filePath}`,\n\t\t\tdetails: [err instanceof Error ? err.message : String(err)],\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\tconst result = JobDefinitionSchema.safeParse(parsed);\n\tif (!result.success) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Validation failed for ${filePath}`,\n\t\t\tdetails: formatZodErrors(result.error),\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\treturn {\n\t\tsuccess: true,\n\t\tdefinition: result.data,\n\t\tfilePath,\n\t};\n}\n\n// ============================================================================\n// Junction YAML Loading\n// ============================================================================\n\nexport interface JunctionLoadResult {\n\tsuccess: true;\n\tdefinition: JunctionDefinition;\n\tfilePath: string;\n}\n\nexport interface JunctionLoadError {\n\tsuccess: false;\n\terror: string;\n\tdetails?: string[];\n\tfilePath: string;\n}\n\nexport type LoadJunctionResult = JunctionLoadResult | JunctionLoadError;\n\n/**\n * Load and validate a junction definition from a YAML file.\n *\n * Mirrors {@link loadRelationshipFromYaml}: existence check → readFileSync →\n * parseYaml → `JunctionDefinitionSchema.safeParse`. Returns a discriminated\n * result; callers are expected to aggregate into `AnalysisIssue`s rather\n * than throw.\n */\nexport function loadJunctionFromYaml(filePath: string): LoadJunctionResult {\n\tif (!existsSync(filePath)) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `File not found: ${filePath}`,\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\tlet content: string;\n\ttry {\n\t\tcontent = readFileSync(filePath, 'utf-8');\n\t} catch (err) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Failed to read file: ${filePath}`,\n\t\t\tdetails: [err instanceof Error ? err.message : String(err)],\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = parseYaml(content);\n\t} catch (err) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Invalid YAML syntax in ${filePath}`,\n\t\t\tdetails: [err instanceof Error ? err.message : String(err)],\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\tconst result = JunctionDefinitionSchema.safeParse(parsed);\n\tif (!result.success) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Validation failed for ${filePath}`,\n\t\t\tdetails: formatZodErrors(result.error),\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\treturn {\n\t\tsuccess: true,\n\t\tdefinition: result.data,\n\t\tfilePath,\n\t};\n}\n\n/**\n * Load multiple junction files.\n */\nexport function loadJunctionsFromYaml(filePaths: string[]): {\n\tsuccesses: JunctionLoadResult[];\n\tfailures: JunctionLoadError[];\n} {\n\tconst successes: JunctionLoadResult[] = [];\n\tconst failures: JunctionLoadError[] = [];\n\n\tfor (const filePath of filePaths) {\n\t\tconst result = loadJunctionFromYaml(filePath);\n\t\tif (result.success) {\n\t\t\tsuccesses.push(result);\n\t\t} else {\n\t\t\tfailures.push(result);\n\t\t}\n\t}\n\n\treturn { successes, failures };\n}\n\n// ============================================================================\n// Provider YAML Loading (RFC-0001 §1)\n// ============================================================================\n\nexport interface ProviderLoadResult {\n\tsuccess: true;\n\tdefinition: ProviderDefinition;\n\tfilePath: string;\n}\n\nexport interface ProviderLoadError {\n\tsuccess: false;\n\terror: string;\n\tdetails?: string[];\n\tfilePath: string;\n}\n\nexport type LoadProviderResult = ProviderLoadResult | ProviderLoadError;\n\n/**\n * Load and validate a single provider definition from a YAML file.\n *\n * Mirrors {@link loadEntityFromYaml}: existence check → readFileSync →\n * parseYaml → `ProviderDefinitionSchema.safeParse`. This covers only the\n * *intra-file* contract; cross-file rules (slug uniqueness, surface subset,\n * pre-flight import resolution) are applied by `validateProviders()` over the\n * full set of successfully-loaded providers.\n */\nexport function loadProviderFromYaml(filePath: string): LoadProviderResult {\n\tif (!existsSync(filePath)) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `File not found: ${filePath}`,\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\tlet content: string;\n\ttry {\n\t\tcontent = readFileSync(filePath, 'utf-8');\n\t} catch (err) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Failed to read file: ${filePath}`,\n\t\t\tdetails: [err instanceof Error ? err.message : String(err)],\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = parseYaml(content);\n\t} catch (err) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Invalid YAML syntax in ${filePath}`,\n\t\t\tdetails: [err instanceof Error ? err.message : String(err)],\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\tconst result = ProviderDefinitionSchema.safeParse(parsed);\n\tif (!result.success) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Validation failed for ${filePath}`,\n\t\t\tdetails: formatZodErrors(result.error),\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\treturn {\n\t\tsuccess: true,\n\t\tdefinition: result.data,\n\t\tfilePath,\n\t};\n}\n\n/**\n * Load multiple provider files.\n */\nexport function loadProvidersFromYaml(filePaths: string[]): {\n\tsuccesses: ProviderLoadResult[];\n\tfailures: ProviderLoadError[];\n} {\n\tconst successes: ProviderLoadResult[] = [];\n\tconst failures: ProviderLoadError[] = [];\n\n\tfor (const filePath of filePaths) {\n\t\tconst result = loadProviderFromYaml(filePath);\n\t\tif (result.success) {\n\t\t\tsuccesses.push(result);\n\t\t} else {\n\t\t\tfailures.push(result);\n\t\t}\n\t}\n\n\treturn { successes, failures };\n}\n\n/**\n * Detect whether a YAML file is an entity, relationship, or junction definition.\n * Checks for the top-level discriminator key.\n *\n * Junctions are discriminated by `pattern: Junction` (a literal value, not\n * just key presence) so an entity YAML that happens to carry `pattern:\n * Synced` is NOT mistaken for a junction file.\n */\nexport function detectYamlType(\n\tfilePath: string,\n): 'entity' | 'relationship' | 'junction' | 'unknown' {\n\tif (!existsSync(filePath)) return 'unknown';\n\n\ttry {\n\t\tconst content = readFileSync(filePath, 'utf-8');\n\t\tconst parsed = parseYaml(content) as Record<string, unknown>;\n\t\tif (parsed && typeof parsed === 'object') {\n\t\t\t// Junction discriminator is value-sensitive (must be exactly the\n\t\t\t// literal 'Junction'). Check BEFORE 'entity' so we don't mistake\n\t\t\t// a top-level junction file for an entity simply because both\n\t\t\t// schemas could in principle nest a `pattern:` key.\n\t\t\tif (parsed.pattern === 'Junction') return 'junction';\n\t\t\tif ('entity' in parsed) return 'entity';\n\t\t\tif ('relationship' in parsed) return 'relationship';\n\t\t}\n\t} catch {\n\t\t// Fall through\n\t}\n\treturn 'unknown';\n}\n","import { z } from \"zod\";\nimport { DetectionConfigSchema } from \"../../runtime/subsystems/integration\";\n\n/**\n * Entity Definition Schema\n *\n * Generates backend code:\n * - Domain entity + repository interface\n * - Application DTOs, use-cases, queries\n * - Infrastructure Drizzle schema + repository\n * - Presentation controller\n * - NestJS module wiring\n * - Shared Zod schema in packages/db\n *\n * Generates frontend code:\n * - Entity metadata for automatic admin panels\n * - UI type, importance, grouping for fields\n */\n\n// ============================================================================\n// Field Types\n// ============================================================================\n\nconst FieldTypeSchema = z.enum([\n \"string\",\n \"integer\",\n \"decimal\",\n \"boolean\",\n \"uuid\",\n \"date\",\n \"datetime\",\n \"json\",\n \"entity_ref\", // Polymorphic reference: generates {field}EntityType + {field}EntityId columns\n \"string_array\", // Array of strings: generates text[] column\n \"enum\", // Enum type with choices or choices_from\n]);\n\nexport type FieldType = z.infer<typeof FieldTypeSchema>;\n\n// ============================================================================\n// UI Metadata Types\n// ============================================================================\n\nconst UiTypeSchema = z.enum([\n \"text\",\n \"textarea\",\n \"number\",\n \"money\",\n \"percentage\",\n \"email\",\n \"url\",\n \"date\",\n \"datetime\",\n \"boolean\",\n \"enum\",\n \"reference\",\n \"json\",\n \"badge\",\n \"password\",\n]);\n\nexport type UiType = z.infer<typeof UiTypeSchema>;\n\nconst UiImportanceSchema = z.enum([\"primary\", \"secondary\", \"tertiary\"]);\n\nexport type UiImportance = z.infer<typeof UiImportanceSchema>;\n\n/**\n * UI Metadata Schema - Optional field-level UI properties\n *\n * All properties are optional and will be inferred at generation time\n * if not explicitly specified in the YAML definition.\n */\n// ============================================================================\n// Semantic / Analytics Metadata Types\n// ============================================================================\n\nconst AnalyticsAggregationSchema = z.enum([\n 'sum',\n 'min',\n 'max',\n 'count',\n 'count_distinct',\n 'average',\n 'median',\n 'percentile',\n 'sum_boolean',\n]);\n\nconst AnalyticsDimensionTypeSchema = z.enum(['categorical', 'time']);\n\nconst AnalyticsEntityTypeSchema = z.enum(['primary', 'unique', 'foreign', 'natural']);\n\nconst AnalyticsTimeGranularitySchema = z.enum(['day', 'week', 'month', 'quarter', 'year']);\n\nconst AnalyticsVisibilitySchema = z.enum(['internal', 'agent', 'public']);\n\nconst NonAdditiveDimensionSchema = z.union([\n z.string(),\n z.object({\n name: z.string(),\n window_choice: z.string().optional(),\n window_groupings: z.array(z.string()).optional(),\n }),\n]);\n\n/**\n * Semantic Metadata Schema - Optional field-level analytics properties\n *\n * Controls how a field is exposed to the cube.js semantic layer:\n * measures, dimensions, entities, and their configuration.\n */\nconst SemanticMetadataSchema = z.object({\n measure: z.boolean().optional(),\n analytics_aggregation: AnalyticsAggregationSchema.optional(),\n agg_time_dimension: z.string().optional(),\n non_additive_dimension: NonAdditiveDimensionSchema.optional(),\n dimension: z.boolean().optional(),\n dimension_type: AnalyticsDimensionTypeSchema.optional(),\n time_granularity: AnalyticsTimeGranularitySchema.optional(),\n is_partition: z.boolean().optional(),\n entity: z.boolean().optional(),\n entity_type: AnalyticsEntityTypeSchema.optional(),\n entity_role: z.string().optional(),\n analytics_visibility: AnalyticsVisibilitySchema.optional(),\n semantic_expr: z.string().optional(),\n semantic_label: z.string().optional(),\n});\n\nconst UiMetadataSchema = z.object({\n ui_label: z.string().optional(),\n ui_type: UiTypeSchema.optional(),\n ui_importance: UiImportanceSchema.optional(),\n ui_group: z.string().optional(),\n ui_sortable: z.boolean().optional(),\n ui_filterable: z.boolean().optional(),\n ui_visible: z.boolean().optional(),\n ui_placeholder: z.string().optional(),\n ui_help: z.string().optional(),\n ui_format: z.record(z.unknown()).optional(),\n // Key-field curation (ADR-040): curated/displayed fields that drive card &\n // preview surfaces. Names mirror qField / EAV `field_definitions`\n // (`isKeyField` / `keyFieldOrder`) — one metadata vocabulary, multiple homes.\n ui_key_field: z.boolean().optional(),\n ui_key_field_order: z.number().optional(),\n});\n\n// ============================================================================\n// Field Definition\n// ============================================================================\n\n/**\n * Field Definition Schema\n *\n * Semantics:\n * - `required: true` → Field must be provided on CREATE (DTO validation)\n * - `required: false` → Field is optional on CREATE (DTO validation)\n * - `nullable: true` → Database column allows NULL\n * - `nullable: false` (default) → Database column is NOT NULL\n *\n * Common patterns:\n * - `required: true` (nullable defaults to false) → Must provide, cannot be null\n * - `required: false, nullable: true` → Optional field, can be null\n * - `required: true, nullable: true` → INVALID (rejected by validator)\n * - `required: false, nullable: false` → Has default value in DB\n */\n/**\n * Base Field Schema - Core database/type properties\n */\nconst BaseFieldSchema = z.object({\n type: FieldTypeSchema,\n required: z.boolean().optional().default(false),\n nullable: z.boolean().optional().default(false),\n\n // String constraints\n max_length: z.number().int().positive().optional(),\n min_length: z.number().int().nonnegative().optional(),\n\n // Numeric constraints\n min: z.number().optional(),\n max: z.number().optional(),\n\n // Enum/choices (inline definition)\n choices: z.array(z.string()).optional(),\n\n // Enum/choices from external file (e.g., \"relationship_types.yaml\")\n // Mutually exclusive with choices - parser loads file and extracts keys\n choices_from: z.string().optional(),\n\n // Entity reference: allowed entity types for polymorphic refs\n // Required when type is 'entity_ref'\n allowed_types: z.array(z.string()).optional(),\n\n // Default value\n default: z.unknown().optional(),\n\n // Indexing\n index: z.boolean().optional(),\n unique: z.boolean().optional(),\n\n // Foreign key reference (e.g., \"accounts.id\")\n foreign_key: z.string().optional(),\n});\n\n/**\n * Field Definition Schema - Combines base fields with optional UI metadata\n */\nconst FieldDefinitionSchema = BaseFieldSchema.merge(UiMetadataSchema).merge(SemanticMetadataSchema)\n .refine((data) => !(data.required === true && data.nullable === true), {\n message:\n \"'required: true' and 'nullable: true' cannot both be set. A required field cannot be null.\",\n path: [\"required\"],\n })\n .refine(\n (data) => {\n if (data.min_length !== undefined && data.type !== \"string\") {\n return false;\n }\n return true;\n },\n {\n message: \"'min_length' can only be used with type 'string'\",\n path: [\"min_length\"],\n },\n )\n .refine(\n (data) => {\n if (data.max_length !== undefined && data.type !== \"string\") {\n return false;\n }\n return true;\n },\n {\n message: \"'max_length' can only be used with type 'string'\",\n path: [\"max_length\"],\n },\n )\n .refine(\n (data) => {\n if (\n data.min !== undefined &&\n ![\"integer\", \"decimal\"].includes(data.type)\n ) {\n return false;\n }\n return true;\n },\n {\n message: \"'min' can only be used with numeric types\",\n path: [\"min\"],\n },\n )\n .refine(\n (data) => {\n if (\n data.max !== undefined &&\n ![\"integer\", \"decimal\"].includes(data.type)\n ) {\n return false;\n }\n return true;\n },\n {\n message: \"'max' can only be used with numeric types\",\n path: [\"max\"],\n },\n )\n .refine(\n (data) => {\n // entity_ref requires allowed_types\n if (data.type === \"entity_ref\" && !data.allowed_types?.length) {\n return false;\n }\n return true;\n },\n {\n message: \"'entity_ref' type requires 'allowed_types' to be specified\",\n path: [\"allowed_types\"],\n },\n )\n .refine(\n (data) => {\n // allowed_types only valid for entity_ref\n if (data.allowed_types !== undefined && data.type !== \"entity_ref\") {\n return false;\n }\n return true;\n },\n {\n message: \"'allowed_types' can only be used with type 'entity_ref'\",\n path: [\"allowed_types\"],\n },\n )\n .refine(\n (data) => {\n // choices and choices_from are mutually exclusive\n if (data.choices !== undefined && data.choices_from !== undefined) {\n return false;\n }\n return true;\n },\n {\n message: \"'choices' and 'choices_from' cannot both be specified\",\n path: [\"choices_from\"],\n },\n )\n .refine(\n (data) => {\n // enum type requires either choices or choices_from\n if (data.type === \"enum\" && !data.choices?.length && !data.choices_from) {\n return false;\n }\n return true;\n },\n {\n message: \"'enum' type requires either 'choices' or 'choices_from'\",\n path: [\"choices\"],\n },\n )\n .refine(\n (data) => {\n // If measure is true, analytics_aggregation must be present\n if (data.measure === true && !data.analytics_aggregation) {\n return false;\n }\n return true;\n },\n {\n message:\n \"When 'measure' is true, 'analytics_aggregation' must be specified\",\n path: [\"analytics_aggregation\"],\n },\n );\n\nexport type FieldDefinition = z.infer<typeof FieldDefinitionSchema>;\n\n// ============================================================================\n// Relationship Definition\n// ============================================================================\n\nconst RelationshipTypeSchema = z.enum([\"belongs_to\", \"has_many\", \"has_one\"]);\n\n/**\n * on_delete — governs database-level FK cascade behaviour for hard-deletes.\n *\n * Applies only to belongs_to relations; ignored on has_many / has_one.\n * Per ADR-021, this has NO effect under soft-delete: BaseService.delete()\n * issues an UPDATE (sets deleted_at), never a DELETE, so Postgres cascade\n * rules never fire for a soft-deleted parent.\n *\n * | Value | Emitted Drizzle | Postgres behaviour |\n * |-------------|------------------------------|---------------------------------------|\n * | restrict | { onDelete: 'restrict' } | Parent DELETE fails if children exist. DEFAULT. |\n * | cascade | { onDelete: 'cascade' } | Parent DELETE removes children. |\n * | set_null | { onDelete: 'set null' } | Parent DELETE nulls FK on children. Requires nullable: true. |\n * | no_action | { onDelete: 'no action' } | Deferred check (equivalent to restrict in single-statement txns). |\n *\n * See docs/adrs/ADR-021-on-delete-semantics.md for the full decision.\n */\nexport const OnDeleteSchema = z.enum([\"restrict\", \"cascade\", \"set_null\", \"no_action\"]);\n\nexport type OnDelete = z.infer<typeof OnDeleteSchema>;\n\nconst RelationshipSchema = z\n .object({\n type: RelationshipTypeSchema,\n target: z.string(), // Target entity name (e.g., \"account\")\n foreign_key: z.string(), // FK field name (e.g., \"account_id\")\n through: z.string().optional(), // For transitive: \"owned_opportunities.updates\"\n inverse: z.string().optional(), // Name of inverse relationship on target entity\n nullable: z.boolean().optional(), // Whether the FK column allows NULL\n on_delete: OnDeleteSchema.optional().default(\"restrict\"), // FK cascade action (belongs_to only; hard-delete only)\n })\n .strict()\n .refine(\n (data) => {\n // set_null requires nullable: true — Postgres cannot null a NOT NULL column\n if (data.on_delete === \"set_null\" && data.nullable !== true) {\n return false;\n }\n return true;\n },\n {\n message:\n \"'on_delete: set_null' requires 'nullable: true' — Postgres cannot null a NOT NULL FK column.\",\n path: [\"on_delete\"],\n },\n );\n\nexport type Relationship = z.infer<typeof RelationshipSchema>;\n\n// ============================================================================\n// Behavior Configuration\n// ============================================================================\n\n/**\n * Behavior configuration can be:\n * - A simple string: \"timestamps\"\n * - An object with options: { name: \"sluggable\", options: { source: \"title\" } }\n *\n * Built-in behaviors:\n * - timestamps: Adds created_at, updated_at fields\n * - soft_delete: Adds deleted_at field, filters deleted records\n * - user_tracking: Adds created_by, updated_by fields\n * - temporal_validity: Adds valid_from, valid_to, is_active fields\n * with deactivate() method and validity-aware query filtering\n */\nconst BehaviorConfigSchema = z.union([\n z.string(),\n z.object({\n name: z.string(),\n options: z.record(z.unknown()).optional(),\n }),\n]);\n\nexport type BehaviorConfig = z.infer<typeof BehaviorConfigSchema>;\n\n/**\n * Behavior strategy for repository code generation\n * - base_class: Extend BaseRepository (DRY, recommended)\n * - inline: Generate all code directly (WET, full transparency)\n */\nconst BehaviorStrategySchema = z.enum([\"base_class\", \"inline\"]);\n\nexport type BehaviorStrategy = z.infer<typeof BehaviorStrategySchema>;\n\n// ============================================================================\n// Entity Configuration\n// ============================================================================\n\n/**\n * Layout: Folder structure - controls directory nesting\n * - nested: domain/opportunity/opportunity.entity.ts\n * - flat: domain/opportunity.entity.ts\n */\nconst FolderStructureSchema = z.enum([\"nested\", \"flat\"]).default(\"nested\");\n\n/**\n * Layout: File grouping - controls how related code is organized\n * - separate: Each concern in its own file (entity.ts, repository.interface.ts)\n * - grouped: Related concerns combined into index.ts\n *\n * This is orthogonal to folder_structure:\n * | folder_structure | file_grouping | Result |\n * |-----------------|---------------|--------|\n * | nested | separate | domain/opportunity/opportunity.entity.ts |\n * | nested | grouped | domain/opportunity/index.ts (combined) |\n * | flat | separate | domain/opportunity.entity.ts |\n * | flat | grouped | domain/opportunity.ts (combined) |\n */\nconst FileGroupingSchema = z.enum([\"separate\", \"grouped\"]).default(\"separate\");\n\n/**\n * Expose configuration - which layers to generate for this entity\n * - repository: Always generated (domain entity, repository interface/impl)\n * - rest: Generate REST controller\n * - trpc: Generate tRPC module\n * - electric: Generate Electric SQL migration (REPLICA IDENTITY + publication)\n *\n * Default: ['repository', 'rest', 'trpc'] (all layers)\n */\nconst ExposeLayerSchema = z.enum([\"repository\", \"rest\", \"trpc\", \"electric\"]);\nexport type ExposeLayer = z.infer<typeof ExposeLayerSchema>;\n\nconst EntityConfigSchema = z\n .object({\n name: z\n .string()\n .regex(\n /^[a-z][a-z0-9_]*$/,\n \"Entity name must be lowercase with underscores (e.g., 'opportunity')\",\n ),\n plural: z.string().regex(/^[a-z][a-z0-9_]*$/, \"Plural must be lowercase\"),\n table: z.string().regex(/^[a-z][a-z0-9_]*$/, \"Table must be lowercase\"),\n\n // Layout options (orthogonal concerns)\n // folder_structure: controls directory nesting\n // file_grouping: controls file organization\n folder_structure: FolderStructureSchema.optional(),\n file_grouping: FileGroupingSchema.optional(),\n\n // Per-entity behavior strategy override (overrides codegen.config.yaml)\n behavior_strategy: BehaviorStrategySchema.optional(),\n // Which layers to generate (default: all)\n expose: z\n .array(ExposeLayerSchema)\n .optional()\n .default([\"repository\", \"rest\", \"trpc\"]),\n\n // App-defined patterns (ADR-031, supersedes ADR-005 family:).\n // `pattern:` and `patterns:` are mutually exclusive — use `pattern:`\n // for a single pattern and `patterns:` for multi-pattern composition.\n // Pattern names resolve against the registry at codegen time.\n pattern: z.string().optional(),\n patterns: z.array(z.string()).optional(),\n // Per-pattern config, keyed by pattern name. Each value is validated\n // against the pattern's `configSchema` in composition validation\n // (src/patterns/validate-composition.ts — PATTERN-4).\n config: z.record(z.string(), z.unknown()).optional(),\n\n // JOB-7: marks this entity as a valid scope target for job scoping.\n // Drives the generated ScopeEntityType union in\n // runtime/subsystems/jobs/generated/scope-entity-type.ts.\n scopeable: z.boolean().optional(),\n\n // RFC-0001 §1/§8: the integration *surface* this entity belongs to\n // (e.g. 'calendar', 'mail', 'crm'). Surfaces span provider contexts\n // (ADR-0006) — one Google OAuth feeds calendar+mail+transcript. The union\n // of `surface:` values across all entity YAML is the closed set that a\n // provider's `surfaces:` must be a subset of (cross-checked in\n // src/parser/validate-providers.ts). Optional: entities without an\n // integration surface omit it. The surface-package *emission* convention\n // is Track C (#329); this field is only the declarative input both tracks\n // read. Lives inside the `entity:` block (next to `pattern:`/`name:`/`table:`).\n surface: z.string().optional(),\n\n // Bounded-context declaration (ADR-0004) — \"which bounded context this\n // entity belongs to\". This is the DURABLE decision; it is a plain\n // bounded-context slug, NOT a folder knob. Different features consume it:\n //\n // - #403 (the FIRST consumer): drives the generated code's\n // module output folder. clean-lite-ps nests the entity's module under\n // `<modules>/<context>/<entity>/` so same-context entities group\n // together; untagged entities stay flat (`<modules>/<entity>/`).\n // - ADR-0004 (deferred): a later `naming: prefix | schema` knob reads\n // this SAME field to drive the Postgres physical layout —\n // `prefix` → `pgTable('<context>__<table>')`, then the flip to\n // `schema` → `pgSchema('<context>').table('<table>')`. NOT wired here.\n //\n // Sibling to `surface:` and orthogonal to it (ADR-0006): context = model\n // cohesion (which domain), surface = vendor composition (which integration).\n // Lives inside the `entity:` block (next to `pattern:`/`name:`/`table:`).\n context: z\n .string()\n .regex(\n /^[a-z][a-z0-9_]*$/,\n \"context must be lowercase snake_case (e.g. 'integration')\",\n )\n .optional(),\n\n // ADR-038: per-entity frontend sync mode. Overrides global frontend.sync.mode.\n // 'api' → queryCollectionOptions (REST via TanStack Query)\n // 'electric' → electricCollectionOptions (real-time shape sync)\n // 'offline' (Electric + Dexie) is deferred — see\n // docs/specs/2026-06-04-frontend-pipeline-rebuild.md OQ-6.\n // Sibling to `surface:`/`context:`; lives inside the `entity:` block.\n sync: z.enum(['api', 'electric']).optional(),\n })\n .strict()\n .refine((d) => !(d.pattern && d.patterns), {\n message: \"'pattern' and 'patterns' are mutually exclusive\",\n });\n\nexport type EntityConfig = z.infer<typeof EntityConfigSchema>;\n\n// ============================================================================\n// Query Declaration\n// ============================================================================\n\n/**\n * Query Declaration Schema - Declarative query generation (ADR-005)\n *\n * Each declaration generates repository + service + use case methods.\n *\n * Examples:\n * { by: [\"user_id\"] }\n * { by: [\"email\"], unique: true }\n * { by: [\"account_id\"], order: \"created_at desc\", limit: true }\n * { by: [\"opportunity_id\"], select: [\"email\"], via: \"opportunity_contact_link\" }\n */\nconst QueryDeclarationSchema = z.object({\n by: z.array(z.string()).min(1),\n unique: z.boolean().optional(),\n select: z.array(z.string()).optional(),\n order: z.string().optional(),\n limit: z.boolean().optional(),\n via: z.string().optional(),\n});\n\nexport type QueryDeclaration = z.infer<typeof QueryDeclarationSchema>;\n\n/**\n * Search Query Declaration — filtered search with pagination.\n *\n * Emits:\n * - `searchXs(input): Promise<Page<Entity>>` on the service\n * - `GET /xs/search` controller route with Zod filter schema\n * - `SearchXsUseCase` with filter-AND + count-for-total semantics\n *\n * Example:\n * - name: search\n * filters: [user_id, provider, is_visible, canonical_state, is_closed]\n * search: name # optional ilike on a single text column\n * paginate: true # defaults to limit 50, max 200, offset 0\n *\n * Consumer contract: `@shared/http/pagination` must export\n * `PaginationSchema` (z.object with limit+offset defaults) and a\n * `Page<T>` interface with `{ items, total, limit, offset }`.\n */\nconst SearchQueryDeclarationSchema = z.object({\n name: z.literal('search'),\n filters: z.array(z.string()).min(1),\n search: z.string().optional(),\n paginate: z.boolean().optional().default(true),\n order: z.string().optional(),\n});\n\nexport type SearchQueryDeclaration = z.infer<typeof SearchQueryDeclarationSchema>;\n\n/**\n * Discriminated union: query declarations can be either the legacy\n * by-column findByX form or the named-search form. The two shapes are\n * disjoint (no `name` vs required `name: 'search'`), so consumers can\n * mix them in the same `queries:` block.\n */\nconst AnyQueryDeclarationSchema = z.union([\n SearchQueryDeclarationSchema,\n QueryDeclarationSchema,\n]);\n\n// ============================================================================\n// Integration Configuration\n// ============================================================================\n\n/**\n * Direction of integration with an external provider\n */\nexport const IntegrationDirectionSchema = z.enum([\n 'inbound',\n 'outbound',\n 'bidirectional',\n]);\n\nexport type IntegrationDirection = z.infer<typeof IntegrationDirectionSchema>;\n\n/**\n * Per-provider integration configuration\n */\nexport const ProviderIntegrationSchema = z.object({\n remote_entity: z.string(),\n direction: IntegrationDirectionSchema,\n cdc: z.boolean().optional().default(false),\n field_mapping: z.record(z.string(), z.string()).optional(),\n read_only_fields: z.array(z.string()).optional(),\n});\n\nexport type ProviderIntegration = z.infer<typeof ProviderIntegrationSchema>;\n\n// ============================================================================\n// Sink Policy (per-entity, lives under integration.sink)\n// ============================================================================\n\n/**\n * Per-entity sink policy knobs (schema → parser → emitter, #490).\n *\n * Attached to the `integration:` block as `integration.sink` so the knobs live\n * alongside the provider/surface config that drives the same integration layer.\n *\n * - `delete` — tri-state delete policy:\n * - `soft` → repo `softDelete: true` (set deletedAt)\n * - `tombstone` → repo `softDelete: false` (null externalId/provider)\n * - `noop` → sink short-circuits, returns null; repo config left at !!hasSoftDelete default.\n * Absent (no `.default`) → preserves current behavior: `!!hasSoftDelete`.\n * DO NOT add a `.default()` here — it would silently flip every soft_delete-free entity.\n *\n * - `exclude_fields` — string array of field names to drop from the copy-through\n * write surface (writeColumns/writeFields AND copyThroughFields). Validated by\n * superRefine on EntityDefinitionSchema: must be declared copy-through scalars\n * (not FK columns, not user_id). Excluded fields are absent from the write\n * surface entirely (no-clobber by construction) and from the #488 find view\n * (shared copyThroughFields input — symmetrically absent on both sides so the\n * differ never compares them; see spec §Find-side).\n *\n * - `emit_changes` — opt-in post-upsert change-event emission (EMIT-CHANGES seam).\n * When `true`, codegen (a) desugars the entity into three change events\n * `<entity>_created` / `<entity>_edited` / `<entity>_deleted` (merged into the\n * generated events registry exactly like a hand-authored `events/*.yaml`), and\n * (b) binds an `INTEGRATION_CHANGE_EMITTER` in the per-entity integration\n * assembly so `ExecuteIntegrationUseCase` publishes the typed event after every\n * sink write/soft-delete. Absent/false ⇒ no emission (back-compat default).\n * The verb is `_edited`, NOT `_updated` (swe-brain ADR-0009 B1 vocabulary).\n */\nconst SinkPolicySchema = z.object({\n delete: z\n .enum(['soft', 'tombstone', 'noop'])\n .optional(), // NO .default() — see default fence in spec §Goal\n exclude_fields: z.array(z.string()).optional(),\n emit_changes: z.boolean().optional(), // NO .default() — absent ⇒ no emission\n}).strict();\n\nexport type SinkPolicy = z.infer<typeof SinkPolicySchema>;\n\n/**\n * Top-level integration block: Electric SQL + named provider configs\n */\nexport const IntegrationConfigSchema = z.object({\n electric: z.boolean().optional().default(false),\n providers: z.record(z.string(), ProviderIntegrationSchema).optional(),\n sink: SinkPolicySchema.optional(),\n});\n\nexport type IntegrationConfig = z.infer<typeof IntegrationConfigSchema>;\n\n// ============================================================================\n// Event Declaration\n// ============================================================================\n\n/**\n * Event Declaration Schema - Domain event declarations (CODEGEN-EVOLUTION-PLAN Phase 2)\n *\n * Each declaration generates typed event classes, handlers, and queue registration.\n *\n * Example:\n * name: opportunity_stage_changed\n * queue: domain-events\n * body:\n * opportunity_id: uuid\n * old_stage: string\n * generate_handler: true\n */\nconst EventDeclarationSchema = z.object({\n name: z\n .string()\n .regex(/^[a-z][a-z0-9_]*$/, \"Event name must be snake_case\"),\n queue: z.string(),\n body: z.record(z.string(), z.string()),\n generate_handler: z.boolean().optional().default(false),\n});\n\nexport type EventDeclaration = z.infer<typeof EventDeclarationSchema>;\n\n// ============================================================================\n// Analytics Block (entity-level)\n// ============================================================================\n\n/**\n * Simple metric in a YAML metric definition\n */\nconst SimpleMetricSchema = z.object({\n type: z.literal('simple'),\n measure: z.string(),\n agg: AnalyticsAggregationSchema.optional(),\n filter: z.string().optional(),\n description: z.string().optional(),\n label: z.string().optional(),\n});\n\n/**\n * Derived metric — expression combining other metrics\n */\nconst DerivedMetricSchema = z.object({\n type: z.literal('derived'),\n expr: z.string(),\n metrics: z.array(z.string()),\n description: z.string().optional(),\n label: z.string().optional(),\n});\n\n/**\n * Ratio metric — numerator / denominator\n */\nconst RatioMetricSchema = z.object({\n type: z.literal('ratio'),\n numerator: z.union([z.string(), SimpleMetricSchema]),\n denominator: z.union([z.string(), SimpleMetricSchema]),\n filter: z.string().optional(),\n description: z.string().optional(),\n label: z.string().optional(),\n});\n\n/**\n * Cumulative metric — time-series accumulation\n */\nconst CumulativeMetricSchema = z.object({\n type: z.literal('cumulative'),\n measure: z.string(),\n window: z.string().optional(),\n grain_to_date: AnalyticsTimeGranularitySchema.optional(),\n description: z.string().optional(),\n label: z.string().optional(),\n});\n\n/**\n * Discriminated union of all four metric types\n */\nconst MetricDefinitionSchema = z.discriminatedUnion('type', [\n SimpleMetricSchema,\n DerivedMetricSchema,\n RatioMetricSchema,\n CumulativeMetricSchema,\n]);\n\nexport type MetricDefinition = z.infer<typeof MetricDefinitionSchema>;\n\n/**\n * Entity-level analytics block\n *\n * Declared in the YAML under `analytics:` alongside fields and relationships.\n */\nconst AnalyticsBlockSchema = z.object({\n measure_packs: z.array(z.string()).optional(),\n cube_name: z.string().optional(),\n metrics: z.record(z.string(), MetricDefinitionSchema).optional(),\n});\n\nexport type AnalyticsBlock = z.infer<typeof AnalyticsBlockSchema>;\n\n// ============================================================================\n// Full Entity Definition\n// ============================================================================\n\n// ============================================================================\n// Generation Toggles\n// ============================================================================\n\n/**\n * Per-entity opt-outs for code generation.\n *\n * - `writes`: when `false`, suppresses create/update/delete use cases,\n * matching controller routes, and module providers. Defaults to `true`.\n */\nconst GenerateConfigSchema = z\n .object({\n writes: z.boolean().optional().default(true),\n })\n .strict();\n\nexport type GenerateConfig = z.infer<typeof GenerateConfigSchema>;\n\nexport const EntityDefinitionSchema = z\n .object({\n entity: EntityConfigSchema,\n fields: z.record(z.string(), FieldDefinitionSchema),\n relationships: z.record(z.string(), RelationshipSchema).optional(),\n // Behaviors add cross-cutting concerns (timestamps, soft_delete, user_tracking, etc.)\n behaviors: z.array(BehaviorConfigSchema).optional().default([]),\n\n // Per-entity generation toggles (e.g. disable write-side emission)\n generate: GenerateConfigSchema.optional(),\n\n // EAV (entity-attribute-value) dual-write + paired reads (ADR-13).\n // When `true`, codegen emits:\n // - FindXWithFieldsUseCase + ListXWithFieldsUseCase (paired reads)\n // - CreateX / UpdateX use cases in transactional compound-write shape\n // (composes entity service + FieldValueService in one db.transaction,\n // splits `{ fields, ...core }` from the DTO)\n // - GET /:id/with-fields + GET /with-fields controller routes\n // - Service with injected FieldValueRepository + findByIdWithFields /\n // listWithFields paired read methods\n //\n // Consumer contract (must be in place before regen):\n // - BaseService.create/update/delete accept optional `tx` parameter\n // - `@shared/eav-helpers` exports `toEavRows(entityId, entityType, fields)`\n // and `mergeEavRows(rows)`\n // - FieldValueService exposes `upsertMany(rows, tx?)` (inherited from\n // MetadataEntityService)\n // - DRIZZLE_DB injection token available via `@shared/constants/tokens`\n //\n // Defaults to `false` — opt in per entity that needs dynamic/custom fields.\n eav: z.boolean().optional().default(false),\n\n // Declare this entity IS an EAV value table. When `true`, codegen emits\n // the compound EAV methods (upsertFieldsTransactional, findMergedByEntity)\n // on the service and the upsertCurrentValues method on the repository —\n // no hand extension required. Companion flag `eav_definition_table`\n // identifies the sibling entity that stores the field-key ↔ id lookup.\n //\n // Mutually exclusive with `eav: true` in practice — a value table holds\n // OTHER entities' dynamic fields, it isn't itself an EAV-opt-in entity.\n //\n // Assumption (v1): value tables have a `user_id` column. Future\n // `eav_user_scoped: false` flag will relax this for audit/system EAV.\n eav_value_table: z.boolean().optional().default(false),\n\n // Singular entity name of the field-definitions entity that pairs with\n // this value table (matches the `target:` convention in relationship\n // YAMLs). Required when `eav_value_table: true`; ignored otherwise.\n eav_definition_table: z.string().optional(),\n\n\n // v2: Declarative query generation (ADR-005)\n // Generates repository + service + use case methods from declarations\n queries: z.array(AnyQueryDeclarationSchema).optional(),\n\n // v2: Integration integration configuration (CODEGEN-EVOLUTION-PLAN Phase 2)\n // Electric SQL + provider integration (Salesforce, HubSpot, etc.)\n integration: IntegrationConfigSchema.optional(),\n\n // ADR-033.1: Provider-keyed change-source detection.\n //\n // Map of provider name → DetectionConfig. Single-provider entities use\n // a one-key map; multi-provider entities list each provider as a\n // separate key. Each value is an independent `DetectionConfig` (its\n // own mode/cursor/mapping/filters) sourced from the canonical schema\n // in `runtime/subsystems/integration` so this validator and the runtime\n // parser stay in lockstep.\n //\n // Within-file cross-check (ADR-033.1 §6): every key here must also\n // appear in `integration.providers` — see the superRefine on\n // `EntityDefinitionSchema` below.\n detection: z.record(z.string(), DetectionConfigSchema).optional(),\n\n // NOTE: `surface:` and `context:` moved INTO EntityConfigSchema (the\n // `entity:` block) in 0.12.2 — consumers write them next to\n // `pattern:`/`name:`/`table:`, which is the natural place. They are\n // read via `entity.surface` / `entity.context`. Clean break: no\n // root-level placement is accepted.\n\n // v2: Domain event declarations (CODEGEN-EVOLUTION-PLAN Phase 2)\n // Generates typed event classes, handlers, and queue registration\n events: z.array(EventDeclarationSchema).optional(),\n\n // EVT-7: Opt-in typed event emission. Each entry names an `EventDefinition`\n // (top-level `events/<type>.yaml` or an inline `events:` block entry) that\n // the generated use-cases should publish via `TypedEventBus.publish(...)`\n // inside a Drizzle transaction.\n //\n // emits: [contact_created, contact_updated]\n //\n // Cross-validated in `validateEntityEmits()` against the merged event\n // registry. `undefined` ⇒ fallback to untyped lifecycle-events + warning;\n // `[]` ⇒ explicit opt-out, no warning, no typed emission.\n emits: z\n .array(\n z\n .string()\n .regex(/^[a-z][a-z0-9_]*$/, 'emits entries must be snake_case event type names'),\n )\n .optional(),\n\n // v2: Analytics / semantic layer configuration\n // Cube.js measure packs, custom cube name, and metric definitions\n analytics: AnalyticsBlockSchema.optional(),\n\n // Composite (multi-column) unique indexes (#356). Single-column uniqueness\n // is `unique: true` on the field itself; this declares constraints that\n // span 2+ columns, e.g. UNIQUE (conversation_id, sequence). Emitted as a\n // `uniqueIndex(...).on(...)` entry in the generated entity's pgTable\n // extra-config callback. `name` defaults to <table>_<col1>_<col2>_uniq.\n unique_indexes: z\n .array(\n z\n .object({\n fields: z\n .array(z.string())\n .min(2, \"unique_indexes entries span 2+ columns — use `unique: true` on the field for single-column uniqueness\"),\n name: z.string().optional(),\n })\n .strict(),\n )\n .optional(),\n })\n .strict()\n .refine(\n (data) => !data.eav_value_table || typeof data.eav_definition_table === 'string',\n {\n message:\n \"`eav_definition_table` is required when `eav_value_table: true` — \" +\n \"declare the singular entity name of the paired field-definitions entity \" +\n \"(e.g. `eav_definition_table: 'field_definition'`).\",\n path: ['eav_definition_table'],\n },\n )\n .superRefine((entity, ctx) => {\n if (!entity.detection) return;\n const declared = new Set(Object.keys(entity.integration?.providers ?? {}));\n for (const provider of Object.keys(entity.detection)) {\n if (!declared.has(provider)) {\n ctx.addIssue({\n code: 'custom',\n path: ['detection', provider],\n message: `Provider '${provider}' used in detection: but not declared in integration.providers. Known providers: ${[...declared].join(', ')}`,\n });\n }\n }\n })\n .superRefine((entity, ctx) => {\n // Validate integration.sink.exclude_fields: every name must be a declared\n // copy-through scalar field — not a FK column and not user_id.\n // Both are author errors that silently corrupt the write surface — reject loud.\n const excludeFields = entity.integration?.sink?.exclude_fields;\n if (!excludeFields || excludeFields.length === 0) return;\n\n const declaredFields = new Set(Object.keys(entity.fields ?? {}));\n\n // Collect FK column names (belongs_to foreign_key values).\n const fkColumns = new Set<string>();\n for (const rel of Object.values(entity.relationships ?? {})) {\n if (rel.type === 'belongs_to' && typeof rel.foreign_key === 'string') {\n fkColumns.add(rel.foreign_key);\n }\n }\n\n for (let i = 0; i < excludeFields.length; i++) {\n const name = excludeFields[i];\n\n if (!declaredFields.has(name)) {\n ctx.addIssue({\n code: 'custom',\n path: ['integration', 'sink', 'exclude_fields', i],\n message: `exclude_fields: '${name}' is not a declared field. Declared fields: ${[...declaredFields].join(', ')}`,\n });\n continue;\n }\n\n if (fkColumns.has(name)) {\n ctx.addIssue({\n code: 'custom',\n path: ['integration', 'sink', 'exclude_fields', i],\n message: `exclude_fields: '${name}' is a FK column (belongs_to foreign_key). Excluding FK columns corrupts the FK-resolver path — exclude FK columns is not supported. Declare it in exclude_fields only for copy-through scalars.`,\n });\n continue;\n }\n\n if (name === 'user_id') {\n ctx.addIssue({\n code: 'custom',\n path: ['integration', 'sink', 'exclude_fields', i],\n message: `exclude_fields: 'user_id' cannot be excluded. It is used for user-scoping and EAV dual-write; excluding it would break those mechanisms.`,\n });\n }\n }\n });\n\nexport type EntityDefinition = z.infer<typeof EntityDefinitionSchema>;\n\n// ============================================================================\n// Validation Helpers\n// ============================================================================\n\nexport function validateEntityDefinition(data: unknown): EntityDefinition {\n return EntityDefinitionSchema.parse(data);\n}\n\nexport function safeValidateEntityDefinition(data: unknown): {\n success: boolean;\n data?: EntityDefinition;\n error?: z.ZodError;\n} {\n const result = EntityDefinitionSchema.safeParse(data);\n if (result.success) {\n return { success: true, data: result.data };\n }\n return { success: false, error: result.error };\n}\n\n// ============================================================================\n// Type Mapping Utilities (for code generation)\n// ============================================================================\n\n/**\n * Maps YAML field types to TypeScript types\n *\n * Note: 'entity_ref' is handled specially in templates as it generates\n * two fields: {field}EntityType (EntityType enum) and {field}EntityId (string)\n */\nexport const fieldTypeToTypeScript: Record<FieldType, string> = {\n string: \"string\",\n integer: \"number\",\n decimal: \"number\",\n boolean: \"boolean\",\n uuid: \"string\",\n date: \"Date\",\n datetime: \"Date\",\n json: \"unknown\",\n entity_ref: \"EntityRef\", // Placeholder - templates handle specially\n string_array: \"string[]\",\n enum: \"string\", // Actual enum type generated from choices\n};\n\n/**\n * Maps YAML field types to Drizzle column types\n *\n * Note: 'entity_ref' generates two columns: pgEnum + uuid\n * Note: 'enum' uses pgEnum with choices\n */\nexport const fieldTypeToDrizzle: Record<FieldType, string> = {\n string: \"varchar\",\n integer: \"integer\",\n decimal: \"decimal\",\n boolean: \"boolean\",\n uuid: \"uuid\",\n date: \"date\",\n datetime: \"timestamp\",\n json: \"jsonb\",\n entity_ref: \"entity_ref\", // Placeholder - templates handle specially (enum + uuid)\n string_array: \"text().array()\",\n enum: \"enum\", // Placeholder - templates generate pgEnum\n};\n\n/**\n * Maps YAML field types to Zod schema methods\n *\n * Note: 'entity_ref' generates two fields in Zod schema\n * Note: 'enum' uses z.enum() with choices\n */\nexport const fieldTypeToZod: Record<FieldType, string> = {\n string: \"z.string()\",\n integer: \"z.number().int()\",\n // Drizzle maps PG `numeric` to a JS string to preserve precision.\n // Using z.coerce.string() — not z.coerce.number() — prevents silent\n // precision loss on large decimal values. Matches clean-lite-ps (PR #42).\n decimal: \"z.coerce.string()\",\n boolean: \"z.boolean()\",\n uuid: \"z.string().uuid()\",\n date: \"z.date()\",\n datetime: \"z.date()\",\n json: \"z.unknown()\",\n entity_ref: \"entity_ref\", // Placeholder - templates handle specially\n string_array: \"z.array(z.string())\",\n enum: \"z.enum()\", // Placeholder - templates add choices\n};\n","import { z } from \"zod\";\n\n/**\n * Event Definition Schema\n *\n * Describes a single `events/*.yaml` file. This is the codegen-side contract\n * for first-class event declarations (ADR-024 Phase 1, EVT-2). One file per\n * event; filename matches `type` (snake_case). Consumed by EVT-3 to emit\n * `runtime/subsystems/events/generated/` artifacts.\n *\n * Payload field types intentionally narrower than entity field types:\n * events are a wire format, not a database schema. `decimal`, `entity_ref`,\n * `string_array`, `enum` make no sense in an event payload.\n */\n\n// ============================================================================\n// Enums and constants\n// ============================================================================\n\nexport const EVENT_DIRECTIONS = [\"inbound\", \"change\", \"outbound\"] as const;\nexport type EventDirection = (typeof EVENT_DIRECTIONS)[number];\n\n/**\n * Event tiers (AUDIT-1):\n * - `domain` (default) — facts other components may react to. Bridge-eligible.\n * Carries a `direction` and routes through the corresponding\n * `events_*` pool.\n * - `audit` — observational facts about the system itself (sync ran, feature\n * used). NOT bridge-eligible. MUST have no `direction` and no `pool`.\n *\n * See `ai-docs/specs/issue-242/plan.md` for the full design and the EVT\n * skill (`.claude/skills/events/SKILL.md`) for the runtime contract.\n */\nexport const EVENT_TIERS = [\"domain\", \"audit\"] as const;\nexport type EventTier = (typeof EVENT_TIERS)[number];\n\nexport const EVENT_FIELD_TYPES = [\n\t\"uuid\",\n\t\"string\",\n\t\"number\",\n\t\"boolean\",\n\t\"date\",\n\t\"json\",\n\t\"array\",\n] as const;\nexport type EventFieldType = (typeof EVENT_FIELD_TYPES)[number];\n\n/**\n * Scalar types permitted as `items` of an `array` field. Intentionally narrower\n * than the full field-type set: nested arrays and nested objects inside a\n * payload array cross the line from \"wire format\" into \"embedded schema\" and\n * should be modelled either as a separate event or as a `json` blob.\n */\nexport const EVENT_ARRAY_ITEM_TYPES = [\n\t\"uuid\",\n\t\"string\",\n\t\"number\",\n\t\"boolean\",\n\t\"date\",\n] as const;\nexport type EventArrayItemType = (typeof EVENT_ARRAY_ITEM_TYPES)[number];\n\nexport const RESERVED_EVENT_POOLS = [\n\t\"events_inbound\",\n\t\"events_change\",\n\t\"events_outbound\",\n] as const;\nexport type EventPool = (typeof RESERVED_EVENT_POOLS)[number];\n\nexport const EVENT_BACKOFF_STRATEGIES = [\"linear\", \"exponential\"] as const;\nexport type EventBackoffStrategy = (typeof EVENT_BACKOFF_STRATEGIES)[number];\n\n/**\n * Direction → default pool derivation. Each `direction` maps to exactly one\n * reserved pool; overrides must stay within the same category.\n */\nexport const DIRECTION_TO_POOL: Record<EventDirection, EventPool> = {\n\tinbound: \"events_inbound\",\n\tchange: \"events_change\",\n\toutbound: \"events_outbound\",\n};\n\n// ============================================================================\n// Sub-schemas\n// ============================================================================\n\nconst EventDirectionSchema = z.enum(EVENT_DIRECTIONS);\nconst EventTierSchema = z.enum(EVENT_TIERS);\nconst EventFieldTypeSchema = z.enum(EVENT_FIELD_TYPES);\nconst EventArrayItemTypeSchema = z.enum(EVENT_ARRAY_ITEM_TYPES);\nconst EventPoolSchema = z.enum(RESERVED_EVENT_POOLS);\n\n/**\n * Per-payload-field metadata. `nullable: true` means the field may be `null`\n * on the wire; `description` is surfaced into the generated interface/Zod\n * schema as a JSDoc. `items` is required when `type: 'array'` and rejected\n * otherwise — enforces \"array-ness is declared, item shape is declared\"\n * without opening the door to arbitrary nesting.\n */\nconst EventPayloadFieldSchema = z\n\t.object({\n\t\ttype: EventFieldTypeSchema,\n\t\titems: EventArrayItemTypeSchema.optional(),\n\t\tnullable: z.boolean().optional().default(false),\n\t\tdescription: z.string().optional(),\n\t})\n\t.strict()\n\t.superRefine((data, ctx) => {\n\t\tif (data.type === \"array\" && data.items === undefined) {\n\t\t\tctx.addIssue({\n\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\tmessage: \"'items' is required when type is 'array'\",\n\t\t\t\tpath: [\"items\"],\n\t\t\t});\n\t\t}\n\t\tif (data.type !== \"array\" && data.items !== undefined) {\n\t\t\tctx.addIssue({\n\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\tmessage: `'items' is only valid when type is 'array' (got '${data.type}')`,\n\t\t\t\tpath: [\"items\"],\n\t\t\t});\n\t\t}\n\t});\n\nexport type EventPayloadField = z.infer<typeof EventPayloadFieldSchema>;\n\n/**\n * Retry metadata hints surfaced to the drain loop. Default applied at parent\n * level (see `EventDefinitionSchemaCore`).\n */\nconst RetrySchema = z\n\t.object({\n\t\tattempts: z.number().int().min(0).max(20),\n\t\tbackoff: z.enum(EVENT_BACKOFF_STRATEGIES),\n\t})\n\t.strict();\n\nexport type EventRetry = z.infer<typeof RetrySchema>;\n\n/**\n * Declarative time-based emission (ADR-039 — time as an event source). When an\n * event declares `schedule:`, the framework `EventScheduler` materialises one\n * `domain_events` row per (event type, slot) on this cadence; ADR-023's three\n * activation tiers (subscribe / `@JobHandler({ triggers })` / `publishAndStart`)\n * — unchanged — react. No new activation mechanism; time is just a third event\n * source peer to use-case publishes and webhook receivers.\n *\n * `every` is a duration string (`'1h'`, `'30m'`, `'15s'`, `'500ms'`, `'1d'`)\n * or a raw millisecond number — the slot length. Validated at codegen time;\n * re-checked at boot.\n */\nconst DURATION_RE = /^\\s*[0-9]*\\.?[0-9]+\\s*(ms|s|m|h|d)\\s*$/;\n\nexport const ScheduleSchema = z\n\t.object({\n\t\tevery: z.union([\n\t\t\tz\n\t\t\t\t.string()\n\t\t\t\t.regex(\n\t\t\t\t\tDURATION_RE,\n\t\t\t\t\t\"schedule.every must be a duration like '1h', '30m', '15s', '500ms', '1d'\",\n\t\t\t\t),\n\t\t\tz.number().positive().finite(),\n\t\t]),\n\t\t/** Epoch-anchored slot boundaries (default true). */\n\t\talign: z.boolean().optional().default(true),\n\t\t/** Backfill missed slots on recovery (default false → run once). */\n\t\tcatchUp: z.boolean().optional().default(false),\n\t\t/** Upper bound on `catchUp` backfill (default 1000). */\n\t\tmaxCatchUpSlots: z.number().int().positive().optional().default(1000),\n\t})\n\t.strict();\n\nexport type EventSchedule = z.infer<typeof ScheduleSchema>;\n\n// ============================================================================\n// Top-level schema\n// ============================================================================\n\nconst SNAKE_CASE_RE = /^[a-z][a-z0-9_]*$/;\n\n/**\n * Trigger-catalog metadata — the workflow-authoring projection.\n *\n * When an event declares `trigger:`, it is a SELECTABLE workflow trigger: a\n * domain change-fact a directive can fire on (the object is now in our system),\n * as opposed to an inbound transport event whose only job is to sync the DB.\n * Presence is the opt-in — absence means \"not a user-facing trigger\" even for a\n * `direction: change` event (e.g. metadata-churn edits). Consumers PROJECT their\n * trigger catalog from `eventRegistry[type].trigger` instead of hand-maintaining\n * a parallel list, so the catalog can never drift from the event definitions.\n *\n * - `surface` — UI grouping (the domain the trigger belongs to, e.g. 'Mail').\n * - `label` — human label (defaults to a humanised `type` at the consumer).\n * - `description` — short UI copy for the picker.\n * - `fields` — payload paths an author may filter on (snake_case).\n */\nconst EventTriggerSchema = z\n\t.object({\n\t\tsurface: z.string().min(1),\n\t\tlabel: z.string().optional(),\n\t\tdescription: z.string().optional(),\n\t\tfields: z\n\t\t\t.array(\n\t\t\t\tz\n\t\t\t\t\t.string()\n\t\t\t\t\t.regex(\n\t\t\t\t\t\tSNAKE_CASE_RE,\n\t\t\t\t\t\t\"trigger.fields entries must be snake_case payload paths\",\n\t\t\t\t\t),\n\t\t\t)\n\t\t\t.default([]),\n\t})\n\t.strict();\n\nexport type EventTrigger = z.infer<typeof EventTriggerSchema>;\n\nconst EventDefinitionSchemaCore = z\n\t.object({\n\t\ttype: z\n\t\t\t.string()\n\t\t\t.regex(\n\t\t\t\tSNAKE_CASE_RE,\n\t\t\t\t\"Event type must be snake_case starting with a letter\",\n\t\t\t),\n\t\ttier: EventTierSchema.optional().default(\"domain\"),\n\t\tdirection: EventDirectionSchema.optional(),\n\t\tpool: EventPoolSchema.optional(),\n\t\taggregate: z.string().regex(SNAKE_CASE_RE).optional(),\n\t\tsource: z.string().min(1).optional(),\n\t\tdestination: z.string().min(1).optional(),\n\t\tpayload: z\n\t\t\t.record(\n\t\t\t\tz\n\t\t\t\t\t.string()\n\t\t\t\t\t.regex(SNAKE_CASE_RE, \"Payload keys must be snake_case\"),\n\t\t\t\tEventPayloadFieldSchema,\n\t\t\t)\n\t\t\t.default({}),\n\t\tretry: RetrySchema.optional().default({\n\t\t\tattempts: 3,\n\t\t\tbackoff: \"exponential\",\n\t\t}),\n\t\t// ADR-039 — declarative time-based emission. Optional; when present the\n\t\t// platform emits this event on the given cadence (see ScheduleSchema).\n\t\tschedule: ScheduleSchema.optional(),\n\t\tversion: z.number().int().min(1).optional().default(1),\n\t\tdescription: z.string().optional(),\n\t\t// Trigger-catalog projection (workflow authoring). Present ⇒ this event is\n\t\t// a selectable workflow trigger; consumers build the catalog from it. No\n\t\t// refinement ties it to `direction` — selectability is an explicit opt-in,\n\t\t// deliberately decoupled from transport (a change-fact may still be a\n\t\t// non-trigger; an inbound event could opt in if a consumer hydrates it).\n\t\ttrigger: EventTriggerSchema.optional(),\n\t})\n\t.strict();\n\n/**\n * Cross-field refinements (in order):\n *\n * 1. Tier invariants (AUDIT-1):\n * a. `tier: 'audit'` ⇒ `pool` MUST be omitted.\n * b. `tier: 'audit'` ⇒ `direction` MUST be omitted.\n * c. `tier: 'domain'` ⇒ `direction` is required.\n * 2. `direction: change` ⇒ `aggregate` is required.\n * 3. `source` is only valid when `direction: inbound` (strict direction gating).\n * 4. `destination` is only valid when `direction: outbound` (strict direction gating).\n * 5. An explicit `pool` must match `DIRECTION_TO_POOL[direction]`.\n *\n * Strict gating on #3/#4 is a deliberate choice: silent acceptance breeds\n * drift. The ADR defines `source` as inbound-only and `destination` as\n * outbound-only.\n *\n * Refinements #2..#5 are domain-tier-only — audit events have no\n * direction/pool/aggregate/source/destination semantics.\n */\nconst EventDefinitionSchemaRefined = EventDefinitionSchemaCore.superRefine(\n\t(data, ctx) => {\n\t\t// AUDIT-1 — tier invariants. These run first because the rest of\n\t\t// the refinements assume domain semantics (direction populated).\n\t\tif (data.tier === \"audit\") {\n\t\t\tif (data.pool !== undefined) {\n\t\t\t\tctx.addIssue({\n\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\tmessage: `Event '${data.type}' is tier:audit; pool MUST be omitted (got '${data.pool}'). Audit events have no pool. See ai-docs/specs/issue-242/plan.md §AUDIT-2.`,\n\t\t\t\t\tpath: [\"pool\"],\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (data.direction !== undefined) {\n\t\t\t\tctx.addIssue({\n\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\tmessage: `Event '${data.type}' is tier:audit; direction MUST be omitted (got '${data.direction}'). Audit events have no direction. See ai-docs/specs/issue-242/plan.md §AUDIT-2.`,\n\t\t\t\t\tpath: [\"direction\"],\n\t\t\t\t});\n\t\t\t}\n\t\t\t// ADR-039 — a scheduled event must DRIVE work, which means it needs a\n\t\t\t// direction/pool to reach the bridge; audit events route nowhere.\n\t\t\t// v1 keeps `schedule:` domain-tier only.\n\t\t\tif (data.schedule !== undefined) {\n\t\t\t\tctx.addIssue({\n\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\tmessage: `Event '${data.type}' is tier:audit; 'schedule' is not allowed on audit events (they route to no pool and cannot drive the bridge). Make it a domain event with a direction. See ADR-039.`,\n\t\t\t\t\tpath: [\"schedule\"],\n\t\t\t\t});\n\t\t\t}\n\t\t\t// Skip the domain-tier refinements below — they reference\n\t\t\t// `direction`, which is intentionally absent for audit.\n\t\t\treturn;\n\t\t}\n\n\t\t// tier === 'domain' — direction must be present.\n\t\tif (data.direction === undefined) {\n\t\t\tctx.addIssue({\n\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\tmessage: \"'direction' is required when tier is 'domain'\",\n\t\t\t\tpath: [\"direction\"],\n\t\t\t});\n\t\t\t// Bail out — the remaining refinements all read `direction`\n\t\t\t// and would otherwise produce confusing cascade errors.\n\t\t\treturn;\n\t\t}\n\n\t\tif (data.direction === \"change\" && !data.aggregate) {\n\t\t\tctx.addIssue({\n\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\tmessage: \"'aggregate' is required when direction is 'change'\",\n\t\t\t\tpath: [\"aggregate\"],\n\t\t\t});\n\t\t}\n\n\t\tif (data.source !== undefined && data.direction !== \"inbound\") {\n\t\t\tctx.addIssue({\n\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\tmessage: `'source' is only valid when direction is 'inbound' (got '${data.direction}')`,\n\t\t\t\tpath: [\"source\"],\n\t\t\t});\n\t\t}\n\n\t\tif (data.destination !== undefined && data.direction !== \"outbound\") {\n\t\t\tctx.addIssue({\n\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\tmessage: `'destination' is only valid when direction is 'outbound' (got '${data.direction}')`,\n\t\t\t\tpath: [\"destination\"],\n\t\t\t});\n\t\t}\n\n\t\tif (data.pool !== undefined) {\n\t\t\tconst expected = DIRECTION_TO_POOL[data.direction];\n\t\t\tif (data.pool !== expected) {\n\t\t\t\tctx.addIssue({\n\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\tmessage: `pool '${data.pool}' is inconsistent with direction '${data.direction}' (expected '${expected}')`,\n\t\t\t\t\tpath: [\"pool\"],\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t},\n);\n\n/**\n * Final schema: derive `pool` from `direction` when not explicitly set.\n *\n * After `parse()`:\n * - Domain events (`tier === 'domain'`): `pool` and `direction` are both\n * populated; `pool` is derived from `direction` when not explicit.\n * - Audit events (`tier === 'audit'`): `pool` and `direction` both stay\n * `undefined` — audit events have no routing fields by construction\n * (mirrors the `domain_events` CHECK constraint, AUDIT-1).\n */\nexport const EventDefinitionSchema = EventDefinitionSchemaRefined.transform(\n\t(parsed) => {\n\t\tif (parsed.tier === \"audit\") {\n\t\t\t// Audit events: no pool/direction derivation. Both stay undefined.\n\t\t\treturn parsed;\n\t\t}\n\t\t// tier === 'domain': direction is guaranteed present by the refinement.\n\t\t// Narrow the type for the lookup.\n\t\tconst direction = parsed.direction as EventDirection;\n\t\treturn {\n\t\t\t...parsed,\n\t\t\tpool: parsed.pool ?? DIRECTION_TO_POOL[direction],\n\t\t};\n\t},\n);\n\nexport type EventDefinition = z.infer<typeof EventDefinitionSchema>;\n\n// ============================================================================\n// Validation Helpers\n// ============================================================================\n\nexport function validateEventDefinition(data: unknown): EventDefinition {\n\treturn EventDefinitionSchema.parse(data);\n}\n\nexport function safeValidateEventDefinition(data: unknown): {\n\tsuccess: boolean;\n\tdata?: EventDefinition;\n\terror?: z.ZodError;\n} {\n\tconst result = EventDefinitionSchema.safeParse(data);\n\tif (result.success) {\n\t\treturn { success: true, data: result.data };\n\t}\n\treturn { success: false, error: result.error };\n}\n","import { z } from 'zod';\n\n/**\n * Relationship Definition Schema\n *\n * Defines the YAML contract for first-class relationship entities — typed,\n * temporal, sourced junction tables between core entities.\n *\n * A relationship definition generates the same artifacts as an entity\n * (Drizzle schema, repository, DTOs, NestJS module, controller) but with\n * auto-generated FK columns, type enum, temporal fields, and source tracking.\n *\n * The relationship: block replaces entity: as the top-level discriminator.\n * The fields:, queries:, and behaviors: blocks reuse entity-definition schemas.\n *\n * See: docs/codegen-evolution-data-model/03-relationship-taxonomy.md\n * See: test/fixtures/relationships/ for examples\n */\n\n// Re-use field and query schemas from entity-definition\n// These are imported to avoid duplication — fields on a relationship\n// work identically to fields on an entity.\nimport type { FieldDefinition, QueryDeclaration } from './entity-definition.schema.js';\n\n// ============================================================================\n// Relationship Type Definitions\n// ============================================================================\n\n/**\n * Direction metadata for a single relationship type.\n *\n * Required for self-referential relationships (person↔person, org↔org)\n * where direction can't be inferred from entity-type asymmetry.\n *\n * Three mutually exclusive modes:\n * - inverse: \"from→to is called X, to→from is called Y\"\n * - bidirectional: true — direction doesn't matter, query both sides\n * - directed: true — one-way, no inverse name (default if none specified)\n */\nconst TypeDirectionSchema = z\n\t.object({\n\t\t/** Name of the inverse type when viewed from the other direction */\n\t\tinverse: z.string().optional(),\n\t\t/** Both directions are equivalent — queries should check both FK columns */\n\t\tbidirectional: z.boolean().optional(),\n\t\t/** Explicitly directed, no named inverse (default behavior) */\n\t\tdirected: z.boolean().optional(),\n\t})\n\t.refine(\n\t\t(data) => {\n\t\t\tconst set = [data.inverse, data.bidirectional, data.directed].filter(\n\t\t\t\t(v) => v !== undefined,\n\t\t\t);\n\t\t\treturn set.length === 1;\n\t\t},\n\t\t{\n\t\t\tmessage:\n\t\t\t\t'Exactly one of inverse, bidirectional, or directed must be specified',\n\t\t},\n\t);\n\nexport type TypeDirection = z.infer<typeof TypeDirectionSchema>;\n\n/**\n * Relationship types can be declared in two forms:\n *\n * 1. Simple list — for cross-type relationships where direction is\n * unambiguous from entity asymmetry:\n * types: [employed_by, advises, board_member]\n *\n * 2. Object map — for self-referential or when types need direction metadata:\n * types:\n * reporting:\n * inverse: management\n * network:\n * bidirectional: true\n *\n * The simple list is sugar for \"all directed from→to, no inverses.\"\n */\nconst RelationshipTypesSchema = z.union([\n\t// Simple list: all types are directed from→to\n\tz.array(z.string().regex(/^[a-z][a-z0-9_]*$/, 'Type must be snake_case')),\n\t// Object map: each type has direction metadata\n\tz.record(\n\t\tz.string().regex(/^[a-z][a-z0-9_]*$/, 'Type key must be snake_case'),\n\t\tTypeDirectionSchema,\n\t),\n]);\n\nexport type RelationshipTypes = z.infer<typeof RelationshipTypesSchema>;\n\n// ============================================================================\n// On-Delete Semantics (ADR-021)\n// ============================================================================\n\nconst OnDeleteActionSchema = z\n\t.enum(['restrict', 'cascade', 'set_null', 'no_action'])\n\t.default('restrict');\n\nexport type OnDeleteAction = z.infer<typeof OnDeleteActionSchema>;\n\n// ============================================================================\n// Relationship Configuration Block\n// ============================================================================\n\n/**\n * The relationship: block — top-level config for a relationship definition.\n *\n * Establishes the two endpoints, type taxonomy, and behavioral flags.\n * Auto-generates FK columns, type enum, temporal fields, source tracking,\n * and timestamps based on configuration.\n */\nconst RelationshipConfigSchema = z\n\t.object({\n\t\t/** Relationship name (snake_case). Used for class/file naming. */\n\t\tname: z.string().regex(\n\t\t\t/^[a-z][a-z0-9_]*$/,\n\t\t\t'Relationship name must be snake_case',\n\t\t),\n\n\t\t/** Database table name. Defaults to {name}s if not specified. */\n\t\ttable: z\n\t\t\t.string()\n\t\t\t.regex(/^[a-z][a-z0-9_]*$/, 'Table must be snake_case')\n\t\t\t.optional(),\n\n\t\t/** The \"from\" entity — generates {entity}_id FK column (subject). */\n\t\tfrom: z.string().regex(/^[a-z][a-z0-9_]*$/, 'Entity name must be snake_case'),\n\n\t\t/** The \"to\" entity — generates {entity}_id FK column (object). */\n\t\tto: z.string().regex(/^[a-z][a-z0-9_]*$/, 'Entity name must be snake_case'),\n\n\t\t/**\n\t\t * Relationship subtypes. Optional — omit for untyped junctions.\n\t\t * When present, generates a `type` enum column on the junction table.\n\t\t *\n\t\t * Simple list: all types are directed (from→to). Use for cross-type\n\t\t * relationships where entity asymmetry makes direction obvious.\n\t\t *\n\t\t * Object map: each type declares its own direction metadata.\n\t\t * Required for self-referential relationships (from === to).\n\t\t */\n\t\ttypes: RelationshipTypesSchema.optional(),\n\n\t\t/**\n\t\t * Generate temporal validity fields: valid_from (date), valid_to (date?),\n\t\t * is_current (boolean, denormalized for query performance).\n\t\t * Default: true\n\t\t */\n\t\ttemporal: z.boolean().default(true),\n\n\t\t/**\n\t\t * Generate source tracking fields: source (enum), confidence (decimal 0-1).\n\t\t * Default: true\n\t\t */\n\t\tsourced: z.boolean().default(true),\n\n\t\t/** on_delete action for the \"from\" endpoint FK. Default: restrict */\n\t\ton_delete_from: OnDeleteActionSchema.optional(),\n\n\t\t/** on_delete action for the \"to\" endpoint FK. Default: restrict */\n\t\ton_delete_to: OnDeleteActionSchema.optional(),\n\n\t\t/**\n\t\t * Override the default unique constraint columns.\n\t\t *\n\t\t * Defaults:\n\t\t * - Typed: [from_id, to_id, type]\n\t\t * - Typed + temporal: [from_id, to_id, type, valid_from]\n\t\t * - Untyped: [from_id, to_id]\n\t\t *\n\t\t * Use this when the default doesn't fit — e.g., allowing multiple\n\t\t * relationships of the same type between the same entities at different times.\n\t\t */\n\t\tunique_on: z.array(z.string()).optional(),\n\t})\n\t.strict();\n\nexport type RelationshipConfig = z.infer<typeof RelationshipConfigSchema>;\n\n// ============================================================================\n// Query Declaration (reuse from entity-definition)\n// ============================================================================\n\n/**\n * Same query declaration syntax as entities.\n * FK field names in `by:` use the auto-generated names:\n * - Cross-type: {entity}_id (e.g., person_id, organization_id)\n * - Self-referential: from_{entity}_id, to_{entity}_id\n */\nconst RelationshipQuerySchema = z.object({\n\tby: z.array(z.string()).min(1),\n\tunique: z.boolean().optional(),\n\tselect: z.array(z.string()).optional(),\n\torder: z.string().optional(),\n\tlimit: z.boolean().optional(),\n});\n\n// ============================================================================\n// Field Definition (reuse from entity-definition)\n// ============================================================================\n\n// We import the type but need to re-reference the schema inline for Zod parsing.\n// The actual FieldDefinitionSchema is defined in entity-definition.schema.ts.\n// For now, we use z.record(z.string(), z.any()) and validate fields\n// through the shared FieldDefinitionSchema at parse time.\n//\n// TODO: Extract FieldDefinitionSchema to a shared module so both\n// entity-definition and relationship-definition can import it directly.\n\n// ============================================================================\n// Full Relationship Definition\n// ============================================================================\n\n/**\n * Complete relationship definition — the top-level shape of a relationship YAML file.\n *\n * Example (minimal):\n * relationship:\n * name: engagement_opportunity\n * from: engagement\n * to: opportunity\n *\n * Example (full):\n * relationship:\n * name: person_organization\n * table: person_organizations\n * from: person\n * to: organization\n * types: [employed_by, advises, board_member]\n * temporal: true\n * sourced: true\n * fields:\n * role_title:\n * type: string\n * nullable: true\n * queries:\n * - by: [person_id]\n */\nexport const RelationshipDefinitionSchema = z\n\t.object({\n\t\t/** Relationship configuration block */\n\t\trelationship: RelationshipConfigSchema,\n\n\t\t/**\n\t\t * Additional fields beyond auto-generated ones.\n\t\t * These describe the relationship, not either endpoint entity.\n\t\t * Uses the same field definition schema as entity fields.\n\t\t */\n\t\tfields: z.record(z.string(), z.any()).optional(),\n\n\t\t/** Declarative queries — same syntax as entity queries. */\n\t\tqueries: z.array(RelationshipQuerySchema).optional(),\n\t})\n\t.strict()\n\t.refine(\n\t\t(data) => {\n\t\t\t// Self-referential relationships with types MUST use the object map form\n\t\t\t// so that direction metadata (inverse/bidirectional/directed) is explicit.\n\t\t\tif (data.relationship.from === data.relationship.to && data.relationship.types) {\n\t\t\t\treturn !Array.isArray(data.relationship.types);\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\t\t{\n\t\t\tmessage:\n\t\t\t\t'Self-referential relationships must use the object map form for types ' +\n\t\t\t\t'(with inverse/bidirectional/directed metadata), not a simple list',\n\t\t\tpath: ['relationship', 'types'],\n\t\t},\n\t)\n\t.refine(\n\t\t(data) => {\n\t\t\t// Reject fields: keys that collide with auto-generated column names.\n\t\t\t// The reserved set is dynamic — depends on the relationship config.\n\t\t\tif (!data.fields) return true;\n\n\t\t\tconst reserved = getReservedColumnNames(data.relationship);\n\t\t\tconst collisions = Object.keys(data.fields).filter((key) =>\n\t\t\t\treserved.has(key),\n\t\t\t);\n\t\t\treturn collisions.length === 0;\n\t\t},\n\t\t{\n\t\t\tmessage:\n\t\t\t\t'fields: contains keys that collide with auto-generated columns. ' +\n\t\t\t\t'Reserved names depend on config (type, valid_from, valid_to, ' +\n\t\t\t\t'is_current, source, confidence, id, created_at, updated_at, and FK columns).',\n\t\t\tpath: ['fields'],\n\t\t},\n\t);\n\nexport type RelationshipDefinition = z.infer<\n\ttypeof RelationshipDefinitionSchema\n>;\n\n// ============================================================================\n// Validation Helpers\n// ============================================================================\n\nexport function validateRelationshipDefinition(\n\tdata: unknown,\n): RelationshipDefinition {\n\treturn RelationshipDefinitionSchema.parse(data);\n}\n\nexport function safeValidateRelationshipDefinition(data: unknown): {\n\tsuccess: boolean;\n\tdata?: RelationshipDefinition;\n\terror?: z.ZodError;\n} {\n\tconst result = RelationshipDefinitionSchema.safeParse(data);\n\tif (result.success) {\n\t\treturn { success: true, data: result.data };\n\t}\n\treturn { success: false, error: result.error };\n}\n\n// ============================================================================\n// Reserved Column Names\n// ============================================================================\n\n/**\n * Returns the set of column names that are auto-generated for a relationship\n * and therefore cannot be used as custom field names.\n *\n * The set is dynamic — it depends on the relationship config:\n * - Always: id, created_at, updated_at, and both FK columns\n * - If types: present → type\n * - If temporal: true → valid_from, valid_to, is_current\n * - If sourced: true → source, confidence\n */\nexport function getReservedColumnNames(config: RelationshipConfig): Set<string> {\n\tconst { fromColumn, toColumn } = deriveRelationshipFKColumns(config);\n\tconst reserved = new Set([\n\t\t'id',\n\t\t'created_at',\n\t\t'updated_at',\n\t\tfromColumn,\n\t\ttoColumn,\n\t]);\n\n\tif (config.types) {\n\t\treserved.add('type');\n\t}\n\tif (config.temporal) {\n\t\treserved.add('valid_from');\n\t\treserved.add('valid_to');\n\t\treserved.add('is_current');\n\t}\n\tif (config.sourced) {\n\t\treserved.add('source');\n\t\treserved.add('confidence');\n\t}\n\n\treturn reserved;\n}\n\n// ============================================================================\n// Auto-Generated Field Helpers\n// ============================================================================\n\n/**\n * Derives the FK column names for a relationship.\n *\n * Cross-type (from !== to):\n * from: person, to: organization → person_id, organization_id\n *\n * Self-referential (from === to):\n * from: person, to: person → from_person_id, to_person_id\n */\nexport function deriveRelationshipFKColumns(config: RelationshipConfig): {\n\tfromColumn: string;\n\ttoColumn: string;\n} {\n\tif (config.from === config.to) {\n\t\treturn {\n\t\t\tfromColumn: `from_${config.from}_id`,\n\t\t\ttoColumn: `to_${config.to}_id`,\n\t\t};\n\t}\n\treturn {\n\t\tfromColumn: `${config.from}_id`,\n\t\ttoColumn: `${config.to}_id`,\n\t};\n}\n\n/**\n * Derives the default table name if not explicitly specified.\n * Uses the relationship name + 's' suffix.\n */\nexport function deriveTableName(config: RelationshipConfig): string {\n\treturn config.table ?? `${config.name}s`;\n}\n\n/**\n * Collects all type names from a types declaration.\n * Handles both simple list and object map forms.\n */\nexport function collectTypeNames(\n\ttypes: RelationshipTypes | undefined,\n): string[] {\n\tif (!types) return [];\n\tif (Array.isArray(types)) return types;\n\treturn Object.keys(types);\n}\n\n/**\n * Collects all inverse type names from a types declaration.\n * Only applicable for object map form with inverse metadata.\n */\nexport function collectInverseNames(\n\ttypes: RelationshipTypes | undefined,\n): string[] {\n\tif (!types || Array.isArray(types)) return [];\n\treturn Object.values(types)\n\t\t.map((dir) => (dir as TypeDirection & { inverse?: string }).inverse)\n\t\t.filter((v): v is string => v !== undefined);\n}\n\n/**\n * Determines the default unique constraint columns.\n *\n * Logic:\n * - Typed + temporal: [from_id, to_id, type, valid_from]\n * - Typed: [from_id, to_id, type]\n * - Untyped: [from_id, to_id]\n */\nexport function deriveUniqueConstraint(config: RelationshipConfig): string[] {\n\tif (config.unique_on) return config.unique_on;\n\n\tconst { fromColumn, toColumn } = deriveRelationshipFKColumns(config);\n\tconst columns = [fromColumn, toColumn];\n\n\tif (config.types) {\n\t\tcolumns.push('type');\n\t}\n\tif (config.temporal && config.types) {\n\t\tcolumns.push('valid_from');\n\t}\n\n\treturn columns;\n}\n","import { z } from 'zod';\nimport { BASE_JUNCTION_FIELD_NAMES } from '../patterns/library/base-junction-fields.js';\n\n/**\n * Junction Definition Schema\n *\n * Top-level YAML contract for explicit many-to-many junctions between two\n * entities. Sibling to `relationship-definition.schema.ts`: same authoring\n * model (typed, temporal, sourced association), different topology.\n *\n * A junction file's top-level discriminator is `pattern: Junction` (not\n * `entity:` or `relationship:`). The pairing endpoints live in\n * `between: [<entity>, <entity>]` — both intra-domain (e.g.\n * `[opportunity, contact]`) and cross-domain (e.g. `[opportunity, activity]`)\n * are accepted; existence of the named entities is verified by the\n * analyzer in a later leaf, not by this schema.\n *\n * Per-pairing role enums + pairing-specific fields are declared inside the\n * consumer YAML's `fields:` block. They are NEVER shared across pairings\n * (CLAUDE.md \"Explicit junctions\"); the schema enforces locality by\n * rejecting indirection syntax via `.strict()`.\n *\n * See: docs/adrs/ADR-031-app-defined-patterns.md\n * See: .ai-docs/stacks/codegen-app-patterns/specs/58.md\n * See: test/fixtures/junctions/ for examples\n */\n\n// ============================================================================\n// Entity Name\n// ============================================================================\n\nconst EntityNameSchema = z\n\t.string()\n\t.regex(/^[a-z][a-z0-9_]*$/, 'Entity reference must be snake_case');\n\n// ============================================================================\n// Junction Definition\n// ============================================================================\n\n/**\n * Top-level junction YAML shape.\n *\n * pattern: Junction\n * between: [opportunity, contact]\n * temporal: true # optional, default true\n * sourced: true # optional, default true\n * fields:\n * role:\n * type: enum\n * values: [champion, decision_maker, influencer]\n * queries:\n * - by: [opportunity_id]\n *\n * Fields use the same shape as entity fields — validated downstream by the\n * template / codegen layer using the existing `FieldDefinitionSchema`.\n * This schema accepts the shape loosely (`z.any()`) and applies only the\n * reserved-column collision check; matches the relationship-schema\n * precedent (`relationship-definition.schema.ts` line ~250).\n */\nexport const JunctionDefinitionSchema = z\n\t.object({\n\t\t/** Discriminator literal — `pattern: Junction`. */\n\t\tpattern: z.literal('Junction'),\n\n\t\t/**\n\t\t * Exactly two endpoint entity names. Both intra- and cross-domain\n\t\t * pairings are accepted; entity existence is validated by the\n\t\t * analyzer in a later leaf.\n\t\t */\n\t\tbetween: z.tuple([EntityNameSchema, EntityNameSchema]),\n\n\t\t/**\n\t\t * Emit BaseJunctionFields temporal columns (`started_at`, `ended_at`,\n\t\t * `matched_at`). Default true. Matches Relationship's `temporal` toggle.\n\t\t */\n\t\ttemporal: z.boolean().optional().default(true),\n\n\t\t/**\n\t\t * Emit BaseJunctionFields sourcing columns (`sourced_from`,\n\t\t * `confidence`). Default true. Matches Relationship's `sourced` toggle.\n\t\t */\n\t\tsourced: z.boolean().optional().default(true),\n\n\t\t/**\n\t\t * Junction-specific fields beyond `BaseJunctionFields`. Includes the\n\t\t * per-pairing role enum (declared inline; never shared across\n\t\t * pairings). Shape is validated downstream by the codegen layer\n\t\t * using the existing entity FieldDefinitionSchema.\n\t\t */\n\t\tfields: z.record(z.string(), z.any()).optional(),\n\n\t\t/**\n\t\t * Declarative queries — same syntax as entity queries. Shape is\n\t\t * validated downstream by the codegen layer.\n\t\t */\n\t\tqueries: z.array(z.any()).optional(),\n\n\t\t/**\n\t\t * Per-side opt-out for parent-service fan-out (CGP-60). When a side\n\t\t * is `false`, the `_inject-parent-service-*` templates emit nothing\n\t\t * on that side (and the corresponding module wiring is skipped).\n\t\t * The junction service body is always emitted regardless. Defaults\n\t\t * to `{ left: true, right: true }`.\n\t\t */\n\t\texpose_on_parent: z\n\t\t\t.object({\n\t\t\t\tleft: z.boolean().optional().default(true),\n\t\t\t\tright: z.boolean().optional().default(true),\n\t\t\t})\n\t\t\t.optional()\n\t\t\t.default({ left: true, right: true }),\n\t})\n\t.strict()\n\t.refine((d) => d.between[0] !== d.between[1], {\n\t\tmessage: '`between` endpoints must be distinct',\n\t\tpath: ['between'],\n\t})\n\t.refine(\n\t\t(d) => {\n\t\t\tconst fieldNames = Object.keys(d.fields ?? {});\n\t\t\treturn !fieldNames.some((n) => BASE_JUNCTION_FIELD_NAMES.has(n));\n\t\t},\n\t\t{\n\t\t\tmessage:\n\t\t\t\t'`fields:` block redeclares a reserved BaseJunctionFields column ' +\n\t\t\t\t'(is_primary, started_at, ended_at, sourced_from, confidence, matched_at)',\n\t\t\tpath: ['fields'],\n\t\t},\n\t);\n\nexport type JunctionDefinition = z.infer<typeof JunctionDefinitionSchema>;\n\n// ============================================================================\n// Validation Helpers\n// ============================================================================\n\nexport function validateJunctionDefinition(data: unknown): JunctionDefinition {\n\treturn JunctionDefinitionSchema.parse(data);\n}\n\nexport function safeValidateJunctionDefinition(data: unknown): {\n\tsuccess: boolean;\n\tdata?: JunctionDefinition;\n\terror?: z.ZodError;\n} {\n\tconst result = JunctionDefinitionSchema.safeParse(data);\n\tif (result.success) {\n\t\treturn { success: true, data: result.data };\n\t}\n\treturn { success: false, error: result.error };\n}\n","/**\n * BaseJunctionFields — shared column shape every junction table carries.\n *\n * Per-pairing role columns and pairing-specific fields are declared in the\n * consumer YAML's `fields:` block and are NOT part of this shape.\n *\n * Exposed as a TS const so two consumers can import it:\n * - `junction.pattern.ts` — registers it as the pattern's\n * column contribution so the\n * registry's `assertHasContribution()`\n * check passes structurally.\n * - `junction-definition.schema.ts` — uses the name set for the\n * reserved-column collision check\n * on the consumer's `fields:` block.\n *\n * See ADR-031 and `.ai-docs/stacks/codegen-app-patterns/specs/58.md`.\n */\n\nimport type { PatternColumnContribution } from '../pattern-definition.js';\n\nexport const BaseJunctionFields: readonly PatternColumnContribution[] = [\n\t{ name: 'is_primary', type: 'boolean' },\n\t{ name: 'started_at', type: 'timestamp' },\n\t{ name: 'ended_at', type: 'timestamp' },\n\t{ name: 'sourced_from', type: 'text' },\n\t{ name: 'confidence', type: 'numeric(5,4)' },\n\t{ name: 'matched_at', type: 'timestamp' },\n] as const;\n\nexport const BASE_JUNCTION_FIELD_NAMES: ReadonlySet<string> = new Set(\n\tBaseJunctionFields.map((c) => c.name),\n);\n","import { z } from \"zod\";\n\n/**\n * Provider Definition Schema (RFC-0001 §1)\n *\n * Providers are first-class declarative artifacts living at\n * `definitions/providers/<provider>.yaml`, flat and sibling to\n * `definitions/entities/`. They are the single source of provider truth —\n * auth strategy, API client, and the surfaces a provider serves —\n * superseding ADR-034's `codegen.config.yaml providers:` block.\n *\n * This module owns the *intra-file* contract (shape + within-file rules such\n * as \"scopes required iff oauth2\" and the `import-path#Export` reference\n * format). *Cross-file* rules — slug uniqueness across the providers dir,\n * `surfaces[]` ⊆ the union of entity `surface:` declarations, and the\n * pre-flight resolution of `auth.strategy` / `client.class` against real\n * exports on disk — live in `src/parser/validate-providers.ts`, because they\n * need the whole provider set and filesystem access that a single-file Zod\n * parse does not have.\n *\n * D1 scope: schema + validation only. Provider/adapter emission is D2+.\n */\n\n// ============================================================================\n// Import reference (`import-path#Export`)\n// ============================================================================\n\n/**\n * `auth.strategy` and `client.class` are written as `import-path#Export`, e.g.\n * `@app/integrations/providers/google/google-oauth.strategy#GoogleOAuthStrategy`.\n *\n * The schema validates the *format* only: a non-empty path, a single `#`, and\n * a valid JS identifier for the export. Whether that export actually exists is\n * a codegen-time, filesystem-bound check performed pre-flight by\n * `validateProviders()` (RFC-0001 §1 \"Validation (pre-flight)\").\n */\nexport const IMPORT_REF_RE = /^[^#\\s]+#[A-Za-z_$][A-Za-z0-9_$]*$/;\n\nconst ImportRefSchema = z\n .string()\n .regex(\n IMPORT_REF_RE,\n \"must be an 'import-path#Export' reference (e.g. '@app/foo/bar.strategy#BarStrategy')\",\n );\n\n/**\n * Split an `import-path#Export` reference into its two halves. Assumes the ref\n * has already passed `IMPORT_REF_RE` (single `#`, valid identifier).\n */\nexport function parseImportRef(ref: string): { path: string; exportName: string } {\n const hash = ref.indexOf(\"#\");\n return { path: ref.slice(0, hash), exportName: ref.slice(hash + 1) };\n}\n\n// ============================================================================\n// Auth\n// ============================================================================\n\n/**\n * `auth.type` gates which sub-fields are required. `scopes` is required iff\n * `oauth2`. The `…` in RFC-0001 §1 signals this enum will grow as new auth\n * shapes land; additions go here.\n */\nexport const AuthTypeSchema = z.enum([\"oauth2\", \"api-key\", \"app-password\"]);\n\nexport type AuthType = z.infer<typeof AuthTypeSchema>;\n\nconst AuthSchema = z\n .object({\n type: AuthTypeSchema,\n // Class implementing the auth subsystem's strategy contract (ADR-031).\n // Pre-flight verified against a real export at codegen time.\n strategy: ImportRefSchema,\n // Required (and non-empty) iff type === 'oauth2'; see refine below.\n scopes: z.array(z.string()).optional(),\n })\n .strict()\n .refine(\n (a) => a.type !== \"oauth2\" || (a.scopes !== undefined && a.scopes.length > 0),\n {\n message:\n \"auth.scopes is required and must be non-empty when auth.type is 'oauth2'\",\n path: [\"scopes\"],\n },\n );\n\n// ============================================================================\n// Client\n// ============================================================================\n\nconst ClientSchema = z\n .object({\n // API client class. Pre-flight verified against a real export.\n class: ImportRefSchema,\n base_url: z.string().url(\"client.base_url must be an absolute URL\"),\n })\n .strict();\n\n// ============================================================================\n// Display (frontend catalog metadata)\n// ============================================================================\n\n/**\n * Presentation metadata consumed ONLY by the frontend providers-catalog\n * emission (`emit-providers.ts`) — never by backend provider/adapter codegen.\n * `category` joins to `frontend.catalog.categories[].id` in\n * `codegen.config.yaml`; providers without a category are exported in the\n * flat `PROVIDERS` list but appear in no catalog group.\n */\nconst DisplaySchema = z\n .object({\n category: z.string().optional(),\n blurb: z.string().optional(),\n // Sub-line shown on an unconnected (\"available\") tile.\n hint: z.string().optional(),\n })\n .strict();\n\n// ============================================================================\n// Full Provider Definition\n// ============================================================================\n\nexport const ProviderDefinitionSchema = z\n .object({\n // Provider id — the canonical string used as detection: keys, audit rows,\n // subscription rows. kebab/lower; unique across definitions/providers/\n // (uniqueness is a cross-file check in validate-providers.ts).\n slug: z\n .string()\n .regex(\n /^[a-z][a-z0-9-]*$/,\n \"slug must be kebab-case lower (e.g. 'google', 'hubspot')\",\n ),\n display_name: z.string().optional(),\n // Lifecycle: 'active' providers drive backend provider/adapter emission\n // and require auth + client. 'planned' providers are roadmap stubs — they\n // appear in the frontend catalog (as unconnectable tiles) but are skipped\n // by all backend emission and by the surface/import cross-checks, so a\n // stub can exist before its surface has entities or its strategy/client\n // are written.\n status: z.enum([\"active\", \"planned\"]).default(\"active\"),\n // Frontend catalog presentation (see DisplaySchema).\n display: DisplaySchema.optional(),\n // Required iff status === 'active'; see superRefine below.\n auth: AuthSchema.optional(),\n client: ClientSchema.optional(),\n // Surfaces this provider serves (ADR-0006: surfaces span contexts — one\n // Google OAuth feeds calendar+mail+transcript). Each must reference a real\n // `surface:` declared on some entity; that cross-check is in\n // validate-providers.ts (skipped for 'planned'). Non-empty enforced here.\n surfaces: z\n .array(z.string())\n .min(1, \"surfaces must list at least one surface\"),\n // Optional auth lifecycle hints consumed by provider-module emission (D2).\n // `refresh_behavior` is left as a free string in D1 — its domain firms up\n // when D2 consumes it; carrying it now keeps the YAML lossless.\n token_lifetime: z.number().int().positive().optional(),\n refresh_behavior: z.string().optional(),\n })\n .strict()\n .superRefine((def, ctx) => {\n if (def.status === \"active\") {\n if (!def.auth) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"auth is required when status is 'active'\",\n path: [\"auth\"],\n });\n }\n if (!def.client) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"client is required when status is 'active'\",\n path: [\"client\"],\n });\n }\n }\n });\n\nexport type ProviderDefinition = z.infer<typeof ProviderDefinitionSchema>;\n\n/**\n * An 'active' provider with auth + client guaranteed present (enforced by the\n * schema's superRefine). Backend emission paths filter to this shape via\n * {@link isActiveProvider}.\n */\nexport type ActiveProviderDefinition = ProviderDefinition & {\n status: \"active\";\n auth: NonNullable<ProviderDefinition[\"auth\"]>;\n client: NonNullable<ProviderDefinition[\"client\"]>;\n};\n\n/**\n * Narrow a parsed definition to the active (emittable) shape. An absent\n * `status` counts as active — the schema defaults it, but definitions\n * constructed directly (tests, programmatic callers) may omit it.\n */\nexport function isActiveProvider(\n def: ProviderDefinition,\n): def is ActiveProviderDefinition {\n return def.status !== \"planned\";\n}\n\n// ============================================================================\n// Validation Helpers\n// ============================================================================\n\nexport function validateProviderDefinition(data: unknown): ProviderDefinition {\n return ProviderDefinitionSchema.parse(data);\n}\n\nexport function safeValidateProviderDefinition(data: unknown): {\n success: boolean;\n data?: ProviderDefinition;\n error?: z.ZodError;\n} {\n const result = ProviderDefinitionSchema.safeParse(data);\n if (result.success) {\n return { success: true, data: result.data };\n }\n return { success: false, error: result.error };\n}\n","import { z } from \"zod\";\nimport { DetectionConfigSchema } from \"../../runtime/subsystems/integration\";\nimport { ScheduleSchema } from \"./event-definition.schema\";\n\n/**\n * Job Definition Schema — the codegen \"jobs\" definition kind (RFC-0005).\n *\n * Describes a single `definitions/jobs/*.yaml` file: a declarative sync-job\n * profile that the codegen jobs emitter compiles into a `@JobHandler` skeleton.\n * The load-bearing A→B contract (swe-brain ADR-0018): a per-adapter sync-profile\n * object IS a `JobDefinition`. swe-brain authors the YAML; codegen compiles it.\n *\n * Two discriminated unions at two altitudes (ADR-0018 D1+D3):\n * - arm `kind` (poll | reconcile | realtime) — the source-USAGE shape, here.\n * - source `mode` (poll | webhook) — the embedded `DetectionConfig`\n * leaf, REUSED verbatim from `runtime/subsystems/integration` (ADR-033),\n * never redefined.\n *\n * Codegen-side resolutions of the brief's §3 (recorded in RFC-0005):\n * - The differ knob is named `differ.unignore` — NOT `dedupe.unignore` — so it\n * does not collide with the runtime `JobHandlerMeta.dedupe` (DedupePolicy\n * `{ key, windowMs }`), one of the eight handler-meta fields this schema\n * surfaces. `differ.unignore` maps to `integration.differ.unignore`.\n * - No `lane` field: it is not a `JobHandlerMeta` field (grep finds it only in\n * JOB-FN-KEY comments about the concurrency *key*). The execution lane is\n * `pool`.\n * - Function-valued `JobHandlerMeta` fields (`scope.from`, `concurrency.key`,\n * `dedupe.key`, `triggers[].map/when`) are NOT authorable in YAML. The schema\n * models the DECLARATIVE surface only: `key`/`from` are `{{field}}` template\n * strings; a trigger declares its `schedule`/`event` and the emitter generates\n * `map`/`when`.\n * - No provider/adapter identity field (RFC-0005 OQ-4, decided (b)). Arms carry\n * only `domain`; provider→use-case resolution stays swe-brain-side (the D5\n * throwaway `(provider,domain)` registry), revisited when codegen #458 lands.\n * A single job spans providers, so this is deliberately NOT a top-level field.\n *\n * Cadence is owned by the JOB (ADR-0018, overriding the brief's D4 event-owned\n * recommendation — \"the job declares its own cadence; I'm not setting up timers\n * then attaching jobs\"). `triggers[]` is a list of two arm shapes (0/1/N):\n * - `schedule` arm — `{ schedule: ScheduleSchema }`, the AUTHORITATIVE cadence.\n * The emitter desugars it into a generated, job-private scheduled event\n * (ADR-039 `schedule:` block → `EventScheduler` tick) PLUS a bridge trigger,\n * exactly as EMIT-CHANGES desugars `emit_changes` into generated change\n * events. Reuses the events `ScheduleSchema` verbatim (one cadence vocabulary).\n * Each schedule arm gets its OWN event — equal cadences do NOT coalesce; a\n * shared tick is opt-in via an authored event + an `event` arm.\n * - `event` arm — `{ event: <snake_case type> }`, references an EXISTING event\n * (webhook doorbell, etc.); the emitter emits a bridge trigger. #8 validates\n * the event exists. No cadence, no drift-check (nothing to drift against).\n *\n * Strictness boundary: the top level and every arm are `.strict()` (stray keys\n * rejected). The embedded `read:` leaf is the IMPORTED `DetectionConfigSchema`,\n * which is NOT strict (ADR-033 — reused verbatim, never widened), so a typo\n * INSIDE `read:`/`poll:`/`webhook:` (e.g. `eventIdFeld`) is silently stripped, not\n * rejected. The #6 loader / #8 validator / #9 smoke gate is the backstop for\n * read-leaf shape — do not add `.strict()` to the imported leaf.\n */\n\n// ============================================================================\n// Enums and constants\n// ============================================================================\n\n/** Mirrors `RetryPolicy.backoff` in `runtime/subsystems/jobs/job-handler.base.ts`. */\nexport const JOB_BACKOFF_STRATEGIES = [\"fixed\", \"exponential\"] as const;\nexport type JobBackoffStrategy = (typeof JOB_BACKOFF_STRATEGIES)[number];\n\n/** Mirrors `ConcurrencyPolicy.collisionMode`. */\nexport const COLLISION_MODES = [\"queue\", \"reject\", \"replace\"] as const;\nexport type CollisionMode = (typeof COLLISION_MODES)[number];\n\n/** Mirrors `JobHandlerMeta.replayFrom`. */\nexport const REPLAY_FROM = [\"scratch\", \"last_step\", \"last_checkpoint\"] as const;\nexport type ReplayFrom = (typeof REPLAY_FROM)[number];\n\n/** Source-usage shapes (ADR-0018). Discriminant of the `arms[]` union. */\nexport const ARM_KINDS = [\"poll\", \"reconcile\", \"realtime\"] as const;\nexport type ArmKind = (typeof ARM_KINDS)[number];\n\nconst SNAKE_CASE_RE = /^[a-z][a-z0-9_]*$/;\n\n// ============================================================================\n// Policy sub-schemas — the declarative (YAML-authorable) projection of the\n// corresponding `JobHandlerMeta` policy types.\n// ============================================================================\n\n/**\n * `RetryPolicy` (job-handler.base.ts). All four fields surfaced; `backoff` is\n * `fixed | exponential` (jobs), distinct from the events `linear | exponential`.\n */\nconst RetryPolicySchema = z\n\t.object({\n\t\tattempts: z.number().int().min(0).max(20),\n\t\tbackoff: z.enum(JOB_BACKOFF_STRATEGIES),\n\t\tbaseMs: z.number().int().positive(),\n\t\tnonRetryableErrors: z.array(z.string().min(1)).optional(),\n\t})\n\t.strict();\n\nexport type JobRetryPolicy = z.infer<typeof RetryPolicySchema>;\n\n/**\n * `ConcurrencyPolicy`. `key` is the `{{field}}` template string form only — the\n * `(input) => string` function form is code-authored (persisted as the\n * `FN_KEY_SENTINEL`) and cannot be expressed in YAML.\n */\nconst ConcurrencyPolicySchema = z\n\t.object({\n\t\tkey: z.string().min(1),\n\t\tcollisionMode: z.enum(COLLISION_MODES),\n\t})\n\t.strict();\n\nexport type JobConcurrencyPolicy = z.infer<typeof ConcurrencyPolicySchema>;\n\n/**\n * `DedupePolicy` — the runtime job-level dedupe WINDOW (`{ key, windowMs }`).\n * Distinct from `differ.unignore` (below). `key` is the template string form.\n */\nconst DedupePolicySchema = z\n\t.object({\n\t\tkey: z.string().min(1),\n\t\twindowMs: z.number().int().positive(),\n\t})\n\t.strict();\n\nexport type JobDedupePolicy = z.infer<typeof DedupePolicySchema>;\n\n/**\n * `ScopeRef` (job-handler.base.ts). `from` is the `{{field}}` template / field\n * path the emitter compiles into `(input) => string`; the function form is not\n * YAML-authorable.\n */\nconst ScopeRefSchema = z\n\t.object({\n\t\tentity: z.string().regex(SNAKE_CASE_RE, \"scope.entity must be snake_case\"),\n\t\tfrom: z.string().min(1),\n\t})\n\t.strict();\n\nexport type JobScopeRef = z.infer<typeof ScopeRefSchema>;\n\n/**\n * Per-job differ override (ADR-0018 D2). Adds field names back into the\n * DeepEqualDiffer's comparison set for this job, on top of the global\n * `integration.differ.unignore`. The classic case is `deletedAt` so tombstones\n * register as a change. Per-job differ WIRING is deferred (D2); the schema\n * freezes the authoring surface so swe-brain can express it today.\n */\nconst DifferOverrideSchema = z\n\t.object({\n\t\t// Deliberately `.min(1)`: the runtime `DeepEqualDifferOptions.unignore` accepts\n\t\t// `[]` (a harmless no-op), but an empty `differ` block in YAML is meaningless\n\t\t// and almost certainly an authoring mistake — reject it rather than silently\n\t\t// accept a pointless block. (Schema is intentionally stricter than the runtime.)\n\t\tunignore: z.array(z.string().min(1)).min(1),\n\t})\n\t.strict();\n\nexport type JobDifferOverride = z.infer<typeof DifferOverrideSchema>;\n\n// ============================================================================\n// Triggers — what fires the job (ADR-0018). A list of two arm shapes; 0/1/N.\n// Cadence is owned by the JOB (the schedule arm), not a separate event YAML.\n// ============================================================================\n\n/**\n * Schedule arm — the AUTHORITATIVE cadence. The emitter desugars it into a\n * generated, job-private scheduled event (ADR-039 `schedule:` block) + a bridge\n * trigger; there is no separately-authored event and therefore no drift-check.\n * Reuses the events `ScheduleSchema` verbatim (`every`/`align`/`catchUp`/\n * `maxCatchUpSlots`) so jobs and events share one cadence vocabulary.\n */\nconst ScheduleTriggerSchema = z\n\t.object({\n\t\tschedule: ScheduleSchema,\n\t})\n\t.strict();\n\n/**\n * Event arm — references an EXISTING event (a webhook doorbell, a domain event).\n * The emitter emits a bridge trigger; the cross-ref validator (breakdown #8)\n * checks the event exists in the generated `eventRegistry`. The runtime\n * `JobTrigger.map`/`when` functions are emitter-generated — not authored here.\n */\nconst EventTriggerSchema = z\n\t.object({\n\t\tevent: z\n\t\t\t.string()\n\t\t\t.regex(SNAKE_CASE_RE, \"trigger.event must be a snake_case event type\"),\n\t})\n\t.strict();\n\n/**\n * A trigger is exactly one of the two arms. A `z.union` over two `.strict()`\n * objects with disjoint keys: `{ schedule }` → schedule arm, `{ event }` →\n * event arm, `{}` or `{ schedule, event }` → rejected (neither matches).\n */\nconst TriggerSchema = z.union([ScheduleTriggerSchema, EventTriggerSchema]);\n\nexport type JobTriggerDef = z.infer<typeof TriggerSchema>;\n\n// ============================================================================\n// Arms — the multi-arm composite (ADR-0018 D1+D3). Discriminated on `kind`,\n// each embedding a `DetectionConfig` leaf (REUSED, not redefined).\n// ============================================================================\n\n/** PollSync — DI-bound adapter walks the delta; cursor ADVANCES. mode: poll. */\nconst PollArmSchema = z\n\t.object({\n\t\tkind: z.literal(\"poll\"),\n\t\tdomain: z.string().regex(SNAKE_CASE_RE, \"arm.domain must be snake_case\"),\n\t\tread: DetectionConfigSchema,\n\t})\n\t.strict();\n\n/**\n * ReconcileSync — windowed `sourceOverride` (now − window), tombstone\n * inference; cursor WITHHELD (never regress the watermark). mode: poll.\n * `cursorWithheld` is `true` by definition (literal) — a reconcile arm that\n * advanced its cursor would not be a reconcile.\n */\nconst ReconcileArmSchema = z\n\t.object({\n\t\tkind: z.literal(\"reconcile\"),\n\t\tdomain: z.string().regex(SNAKE_CASE_RE, \"arm.domain must be snake_case\"),\n\t\twindow: z\n\t\t\t.object({ hours: z.number().positive().finite() })\n\t\t\t.strict(),\n\t\tcursorWithheld: z.literal(true).optional().default(true),\n\t\tread: DetectionConfigSchema,\n\t})\n\t.strict();\n\n/**\n * RealtimeSync — webhook-staging drain (claim/ack in the handler), NOT a peer\n * primitive (ADR-0018 D1). Reuses `mode: webhook`. The staging table is\n * consumer-owned (the package refuses to own it).\n */\nconst RealtimeArmSchema = z\n\t.object({\n\t\tkind: z.literal(\"realtime\"),\n\t\tdomain: z.string().regex(SNAKE_CASE_RE, \"arm.domain must be snake_case\"),\n\t\tstaging: z\n\t\t\t.object({\n\t\t\t\ttable: z.string().min(1),\n\t\t\t\tpushAccelerate: z.boolean().optional(),\n\t\t\t})\n\t\t\t.strict(),\n\t\tread: DetectionConfigSchema,\n\t})\n\t.strict();\n\nconst ArmSchema = z.discriminatedUnion(\"kind\", [\n\tPollArmSchema,\n\tReconcileArmSchema,\n\tRealtimeArmSchema,\n]);\n\nexport type JobArm = z.infer<typeof ArmSchema>;\n\n// ============================================================================\n// Top-level schema\n// ============================================================================\n\nconst JobDefinitionSchemaCore = z\n\t.object({\n\t\ttype: z\n\t\t\t.string()\n\t\t\t.regex(SNAKE_CASE_RE, \"Job type must be snake_case starting with a letter\"),\n\t\t// ── JobHandlerMeta surface (8 fields) ──────────────────────────────────\n\t\tpool: z.string().min(1).optional(),\n\t\tscope: ScopeRefSchema.optional(),\n\t\tretry: RetryPolicySchema.optional(),\n\t\tconcurrency: ConcurrencyPolicySchema.optional(),\n\t\tdedupe: DedupePolicySchema.optional(),\n\t\ttimeoutMs: z.number().int().positive().optional(),\n\t\treplayFrom: z.enum(REPLAY_FROM).optional(),\n\t\t// `triggers` is the 8th meta field, reshaped to the declarative surface.\n\t\ttriggers: z.array(TriggerSchema).default([]),\n\t\t// ── job-definition additions ───────────────────────────────────────────\n\t\tdiffer: DifferOverrideSchema.optional(),\n\t\tarms: z.array(ArmSchema).min(1, \"a job must declare at least one arm\"),\n\t\tdescription: z.string().optional(),\n\t})\n\t.strict();\n\n/**\n * Cross-arm invariant (ADR-0018 D1↔D3): the arm `kind` constrains the embedded\n * source `mode`. A realtime arm drains a `webhook` source; poll/reconcile arms\n * walk a `poll` source. The two-altitude unions are independent everywhere else\n * — a single job freely mixes realtime + poll arms (e.g. `inbound-sync`).\n */\nexport const JobDefinitionSchema = JobDefinitionSchemaCore.superRefine(\n\t(data, ctx) => {\n\t\tdata.arms.forEach((arm, i) => {\n\t\t\tconst mode = arm.read.mode;\n\t\t\tif (arm.kind === \"realtime\" && mode !== \"webhook\") {\n\t\t\t\tctx.addIssue({\n\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\tmessage: `realtime arm '${arm.domain}' requires read.mode 'webhook' (got '${mode}'). Realtime is a webhook-drain shape (ADR-0018 D1).`,\n\t\t\t\t\tpath: [\"arms\", i, \"read\", \"mode\"],\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (\n\t\t\t\t(arm.kind === \"poll\" || arm.kind === \"reconcile\") &&\n\t\t\t\tmode !== \"poll\"\n\t\t\t) {\n\t\t\t\tctx.addIssue({\n\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\tmessage: `${arm.kind} arm '${arm.domain}' requires read.mode 'poll' (got '${mode}').`,\n\t\t\t\t\tpath: [\"arms\", i, \"read\", \"mode\"],\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t},\n);\n\nexport type JobDefinition = z.infer<typeof JobDefinitionSchema>;\n\n// ============================================================================\n// Validation helpers\n// ============================================================================\n\nexport function validateJobDefinition(data: unknown): JobDefinition {\n\treturn JobDefinitionSchema.parse(data);\n}\n\nexport function safeValidateJobDefinition(data: unknown): {\n\tsuccess: boolean;\n\tdata?: JobDefinition;\n\terror?: z.ZodError;\n} {\n\tconst result = JobDefinitionSchema.safeParse(data);\n\tif (result.success) {\n\t\treturn { success: true, data: result.data };\n\t}\n\treturn { success: false, error: result.error };\n}\n","/**\n * Cross-Entity Naming Registry (ADR-038, FE-1)\n *\n * Loads every entity YAML under a directory and exposes an authoritative\n * name → naming-record map so FK target names (file, plural, class, collection\n * var) are resolved against the TARGET entity's own YAML rather than re-derived\n * by pluralizing strings at emit time. Mirrors the pts generator's\n * `_resolve_relationship_targets`: no plural is ever inferred — `plural` is read\n * straight from `entity.plural`.\n *\n * Tolerant of invalid files: malformed YAMLs are reported as `AnalysisIssue`s\n * (same shape as `loadEntities`) rather than thrown, so one bad file does not\n * sink the whole set.\n */\n\nimport { resolve } from 'node:path';\nimport { findYamlFiles } from '../utils/find-yaml-files';\nimport { loadEntityFromYaml, type LoadError } from '../utils/yaml-loader';\nimport type { AnalysisIssue } from '../analyzer/types';\n\nexport interface EntityRegistryEntry {\n\tname: string; // 'deal_state'\n\tplural: string; // authoritative, from YAML entity.plural\n\ttable: string;\n\tclassName: string; // 'DealState' (pascal of name)\n\tclassNamePlural: string;\n\tcamelName: string; // 'dealState'\n\tpluralCamelName: string;\n\tsync: 'api' | 'electric' | null; // null → inherit global frontend.sync.mode\n}\n\nexport interface LoadEntityRegistryResult {\n\tregistry: Map<string, EntityRegistryEntry>; // keyed by entity name\n\tissues: AnalysisIssue[]; // invalid YAMLs reported, not thrown\n}\n\n// snake_case → camelCase / PascalCase, consistent with prompt.js helpers.\nconst camelCase = (s: string): string =>\n\ts.replace(/_([a-z])/g, (_, c: string) => c.toUpperCase());\nconst pascalCase = (s: string): string => {\n\tconst camel = camelCase(s);\n\treturn camel.charAt(0).toUpperCase() + camel.slice(1);\n};\n\n/**\n * Convert a load error to analysis issues (mirrors `loadEntities`'\n * `loadErrorToIssue`).\n */\nfunction loadErrorToIssue(error: LoadError): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [\n\t\t{\n\t\t\tseverity: 'error',\n\t\t\ttype: 'parse_error',\n\t\t\tmessage: error.error,\n\t\t\tpath: error.filePath,\n\t\t},\n\t];\n\n\tif (error.details) {\n\t\tfor (const detail of error.details) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'error',\n\t\t\t\ttype: 'schema_error',\n\t\t\t\tmessage: detail,\n\t\t\t\tpath: error.filePath,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n/**\n * Load the cross-entity naming registry from a directory of entity YAMLs.\n *\n * @param entitiesDir Directory to walk recursively for `*.yaml`/`*.yml`.\n * @returns A name-keyed registry plus any issues encountered (missing dir,\n * malformed files). Never throws.\n */\nexport function loadEntityRegistry(entitiesDir: string): LoadEntityRegistryResult {\n\tconst registry = new Map<string, EntityRegistryEntry>();\n\tconst issues: AnalysisIssue[] = [];\n\n\tconst resolvedDir = resolve(entitiesDir);\n\n\tlet files: string[];\n\ttry {\n\t\tfiles = findYamlFiles(resolvedDir);\n\t} catch {\n\t\tissues.push({\n\t\t\tseverity: 'error',\n\t\t\ttype: 'parse_error',\n\t\t\tmessage: `Failed to read directory: ${resolvedDir}`,\n\t\t\tpath: resolvedDir,\n\t\t});\n\t\treturn { registry, issues };\n\t}\n\n\tfor (const filePath of files) {\n\t\tconst result = loadEntityFromYaml(filePath);\n\n\t\tif (!result.success) {\n\t\t\tissues.push(...loadErrorToIssue(result));\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst { entity } = result.definition;\n\t\tregistry.set(entity.name, {\n\t\t\tname: entity.name,\n\t\t\tplural: entity.plural, // authoritative — never derived\n\t\t\ttable: entity.table,\n\t\t\tclassName: pascalCase(entity.name),\n\t\t\tclassNamePlural: pascalCase(entity.plural),\n\t\t\tcamelName: camelCase(entity.name),\n\t\t\tpluralCamelName: camelCase(entity.plural),\n\t\t\tsync: entity.sync ?? null,\n\t\t});\n\t}\n\n\treturn { registry, issues };\n}\n","/**\n * Provider Cross-Validator (RFC-0001 §1, D1)\n *\n * Runs after the per-file `ProviderDefinitionSchema` parse (which owns the\n * intra-file contract). This module owns the rules a single-file parse cannot\n * express because they need the whole provider set and/or filesystem access:\n *\n * 1. `slug` is unique across `definitions/providers/`.\n * 2. each `surfaces[]` value references a real `surface:` declared on some\n * `definitions/entities/*.yaml` (the union is the closed set; a surface\n * with no entities is an error — nothing to adapt). Emptiness is caught\n * upstream by the schema's `.min(1)`.\n * 3. pre-flight import resolution: `auth.strategy` and `client.class`\n * (`import-path#Export`) resolve to a real export at codegen time, so a\n * typo fails `cdp gen` with a clear message rather than a NestJS DI\n * failure three layers removed from the cause (RFC-0001 §1).\n *\n * Framework-agnostic and pure w.r.t. its inputs — it only *reads* the\n * filesystem to resolve import refs. The CLI surfaces the returned issues.\n *\n * D1 scope: validation only. No emission.\n */\n\nimport { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { isAbsolute, join, resolve } from \"node:path\";\nimport ts from \"typescript\";\nimport type { AnalysisIssue } from \"../analyzer/types\";\nimport {\n isActiveProvider,\n parseImportRef,\n type ProviderDefinition,\n} from \"../schema/provider-definition.schema\";\n\n// ============================================================================\n// Inputs\n// ============================================================================\n\n/** A successfully-loaded provider plus the file it came from. */\nexport interface LoadedProvider {\n definition: ProviderDefinition;\n filePath: string;\n}\n\nexport interface ValidateProvidersOptions {\n /**\n * The closed set of surfaces declared across all entity YAML — every\n * `provider.surfaces[]` value must be a member. Use\n * {@link collectEntitySurfaces} to build it.\n */\n entitySurfaces: Set<string> | Iterable<string>;\n /**\n * Base directory the import refs resolve against (the consumer source root).\n * Required unless `skipImportCheck` is set.\n */\n sourceRoot?: string;\n /**\n * Path-alias prefixes → absolute directories, e.g. `{ '@app': '/abs/src' }`.\n * A ref whose path matches `<alias>` or `<alias>/…` resolves under the mapped\n * directory; otherwise the ref resolves relative to `sourceRoot`. Wiring this\n * from the consumer tsconfig `paths` is D2+; D1 takes it as an explicit input.\n */\n aliases?: Record<string, string>;\n /**\n * Escape hatch: skip the filesystem-bound import pre-flight (e.g. when the\n * consumer source root is not available in the current context). Slug and\n * surface checks still run.\n */\n skipImportCheck?: boolean;\n}\n\n// ============================================================================\n// Entity-surface union\n// ============================================================================\n\n/**\n * Build the closed set of surfaces from loaded entity definitions — the union\n * of every entity's optional `surface:` value. Entities without a surface\n * contribute nothing.\n */\nexport function collectEntitySurfaces(\n entities: Iterable<{ entity: { surface?: string } }>,\n): Set<string> {\n const surfaces = new Set<string>();\n for (const e of entities) {\n if (e.entity.surface) surfaces.add(e.entity.surface);\n }\n return surfaces;\n}\n\n// ============================================================================\n// Import-ref pre-flight\n// ============================================================================\n\nexport type ImportRefResolution =\n | { status: \"ok\"; file: string }\n | { status: \"module-not-found\"; resolvedFrom: string }\n | { status: \"export-not-found\"; file: string };\n\n/**\n * Resolve an `import-path#Export` ref against the source tree and confirm the\n * named export exists.\n *\n * Module resolution: a path matching a configured alias is rewritten under the\n * mapped directory; otherwise it resolves relative to `sourceRoot`. Candidate\n * files tried in order: the path as-is, `.ts`, `.tsx`, `/index.ts`,\n * `/index.tsx`.\n *\n * Export resolution uses the TypeScript parser (not regex) so `export class`,\n * `export const`, `export { X as Name }`, re-exports, and namespace exports are\n * all recognised. A bare `export * from '…'` re-export cannot be disproven\n * without following it, so a ref that matches no concrete export but the module\n * carries a wildcard re-export is treated as resolvable (documented limitation;\n * the typo class this guards is a misspelt path or export *name*, both of which\n * still fail).\n */\nexport function resolveImportRef(\n ref: string,\n opts: { sourceRoot: string; aliases?: Record<string, string> },\n): ImportRefResolution {\n const { path, exportName } = parseImportRef(ref);\n const file = resolveModuleFile(path, opts);\n if (!file) {\n return { status: \"module-not-found\", resolvedFrom: opts.sourceRoot };\n }\n\n const content = readFileSync(file, \"utf-8\");\n const { names, hasWildcard } = collectExportedNames(file, content);\n if (names.has(exportName) || hasWildcard) {\n return { status: \"ok\", file };\n }\n return { status: \"export-not-found\", file };\n}\n\nfunction resolveModuleFile(\n importPath: string,\n opts: { sourceRoot: string; aliases?: Record<string, string> },\n): string | null {\n let base: string | null = null;\n\n for (const [alias, target] of Object.entries(opts.aliases ?? {})) {\n if (importPath === alias || importPath.startsWith(`${alias}/`)) {\n const rest = importPath.slice(alias.length); // includes leading '/' or ''\n base = join(target, rest);\n break;\n }\n }\n\n if (base === null) {\n base = isAbsolute(importPath)\n ? importPath\n : resolve(opts.sourceRoot, importPath);\n }\n\n const candidates = [\n base,\n `${base}.ts`,\n `${base}.tsx`,\n join(base, \"index.ts\"),\n join(base, \"index.tsx\"),\n ];\n for (const c of candidates) {\n if (existsSync(c) && statSync(c).isFile()) return c;\n }\n return null;\n}\n\nfunction collectExportedNames(\n fileName: string,\n content: string,\n): { names: Set<string>; hasWildcard: boolean } {\n const sf = ts.createSourceFile(\n fileName,\n content,\n ts.ScriptTarget.Latest,\n /* setParentNodes */ true,\n );\n const names = new Set<string>();\n let hasWildcard = false;\n\n const hasExportModifier = (node: ts.Node): boolean =>\n ts.canHaveModifiers(node) &&\n (ts.getModifiers(node)?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) ??\n false);\n\n sf.forEachChild((node) => {\n if (hasExportModifier(node)) {\n if (\n (ts.isClassDeclaration(node) ||\n ts.isFunctionDeclaration(node) ||\n ts.isInterfaceDeclaration(node) ||\n ts.isTypeAliasDeclaration(node) ||\n ts.isEnumDeclaration(node) ||\n ts.isModuleDeclaration(node)) &&\n node.name &&\n ts.isIdentifier(node.name)\n ) {\n names.add(node.name.text);\n } else if (ts.isVariableStatement(node)) {\n for (const decl of node.declarationList.declarations) {\n if (ts.isIdentifier(decl.name)) names.add(decl.name.text);\n }\n }\n }\n\n if (ts.isExportDeclaration(node)) {\n if (!node.exportClause) {\n hasWildcard = true; // export * from '…'\n } else if (ts.isNamedExports(node.exportClause)) {\n for (const el of node.exportClause.elements) names.add(el.name.text);\n } else if (ts.isNamespaceExport(node.exportClause)) {\n names.add(node.exportClause.name.text); // export * as ns from '…'\n }\n }\n });\n\n return { names, hasWildcard };\n}\n\n// ============================================================================\n// Cross-validator\n// ============================================================================\n\n/**\n * Cross-validate a set of loaded providers. Never throws — always returns an\n * array of {@link AnalysisIssue} (all `severity: 'error'` for D1's gates).\n */\nexport function validateProviders(\n providers: LoadedProvider[],\n opts: ValidateProvidersOptions,\n): AnalysisIssue[] {\n const issues: AnalysisIssue[] = [];\n const knownSurfaces = new Set(opts.entitySurfaces);\n\n // 1. slug uniqueness across the providers dir.\n const slugToFiles = new Map<string, string[]>();\n for (const p of providers) {\n const files = slugToFiles.get(p.definition.slug) ?? [];\n files.push(p.filePath);\n slugToFiles.set(p.definition.slug, files);\n }\n for (const [slug, files] of slugToFiles) {\n if (files.length > 1) {\n for (const file of files) {\n const others = files.filter((f) => f !== file);\n issues.push({\n severity: \"error\",\n type: \"provider_duplicate_slug\",\n message: `provider slug '${slug}' is declared more than once (also in: ${others.join(\", \")})`,\n path: file,\n });\n }\n }\n }\n\n for (const { definition, filePath } of providers) {\n const { slug } = definition;\n\n // 'planned' providers are roadmap stubs (frontend catalog only): no\n // backend emission consumes them, so the surface closed-set check and the\n // auth/client import pre-flight don't apply. Slug uniqueness (above) does.\n if (definition.status === \"planned\") continue;\n\n // 2. surfaces[] ⊆ entity surface union.\n for (const surface of definition.surfaces) {\n if (!knownSurfaces.has(surface)) {\n const known = [...knownSurfaces].sort().join(\", \") || \"(none declared)\";\n issues.push({\n severity: \"error\",\n type: \"provider_unknown_surface\",\n message: `provider ${slug}: surface '${surface}' is not declared by any entity (known surfaces: ${known})`,\n path: filePath,\n });\n }\n }\n\n // 3. pre-flight import resolution for auth.strategy + client.class.\n if (!opts.skipImportCheck) {\n if (!opts.sourceRoot) {\n throw new Error(\n \"validateProviders: sourceRoot is required for the import pre-flight check (or set skipImportCheck: true)\",\n );\n }\n const resolveOpts = {\n sourceRoot: opts.sourceRoot,\n aliases: opts.aliases,\n };\n if (!isActiveProvider(definition)) continue; // type narrow; planned already skipped above\n const refs: Array<{ field: string; ref: string }> = [\n { field: \"auth.strategy\", ref: definition.auth.strategy },\n { field: \"client.class\", ref: definition.client.class },\n ];\n for (const { field, ref } of refs) {\n const result = resolveImportRef(ref, resolveOpts);\n if (result.status === \"module-not-found\") {\n issues.push({\n severity: \"error\",\n type: \"provider_import_unresolved\",\n message: `provider ${slug}: ${field} '${ref}' not found — module could not be resolved from ${result.resolvedFrom}`,\n path: filePath,\n });\n } else if (result.status === \"export-not-found\") {\n const { exportName } = parseImportRef(ref);\n issues.push({\n severity: \"error\",\n type: \"provider_import_unresolved\",\n message: `provider ${slug}: ${field} '${ref}' not found — export '${exportName}' is missing from ${result.file}`,\n path: filePath,\n });\n }\n }\n }\n }\n\n return issues;\n}\n","/**\n * Job Definition Loader (RFC-0005, breakdown #6)\n *\n * Loads and parses all job YAML files from a directory (default\n * `definitions/jobs/`). Enforces filename ↔ `type` consistency and rejects\n * duplicate job types. Returns a {@link LoadJobsResult} that collects all\n * issues (never throws), matching the `loadEvents()` / `loadEntities()`\n * contract used elsewhere in the parser layer.\n *\n * Deliberately does NOT cross-validate `triggers[].event` against the event\n * registry, nor arm `domain` against entities — those gen-time cross-refs are\n * the cross-ref validator's job (breakdown #8). This loader is shape + filename\n * + uniqueness only; #7 (the emitter) consumes the validated `JobDefinition[]`.\n */\n\nimport { basename, resolve } from 'node:path';\nimport { findYamlFiles } from '../utils/find-yaml-files';\nimport type { AnalysisIssue } from '../analyzer/types';\nimport type { JobDefinition } from '../schema/job-definition.schema';\nimport {\n\tloadJobFromYaml,\n\ttype JobLoadError,\n\ttype LoadJobResult,\n} from '../utils/yaml-loader';\n\nexport interface LoadJobsResult {\n\tjobs: JobDefinition[];\n\tissues: AnalysisIssue[];\n}\n\n/**\n * Convert a job-load error result into one or more {@link AnalysisIssue}s.\n * Mirrors `loadErrorToIssue` in `load-events.ts` so CLI renderers treat both\n * loaders' output uniformly.\n */\nfunction loadErrorToIssue(error: JobLoadError): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\tissues.push({\n\t\tseverity: 'error',\n\t\ttype: 'parse_error',\n\t\tmessage: error.error,\n\t\tpath: error.filePath,\n\t});\n\n\tif (error.details) {\n\t\tfor (const detail of error.details) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'error',\n\t\t\t\ttype: 'schema_error',\n\t\t\t\tmessage: detail,\n\t\t\t\tpath: error.filePath,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n/**\n * Strip `.yaml` / `.yml` from a filename.\n */\nfunction stripYamlExt(file: string): string {\n\tconst base = basename(file);\n\tif (base.endsWith('.yaml')) return base.slice(0, -'.yaml'.length);\n\tif (base.endsWith('.yml')) return base.slice(0, -'.yml'.length);\n\treturn base;\n}\n\n/**\n * Load all job YAML files from a directory.\n *\n * - Nonexistent directory → non-fatal warning, returns empty list (jobs are\n * opt-in, like providers — a project without `definitions/jobs/` is valid).\n * - Empty directory → warning, returns empty list.\n * - Per-file errors (YAML syntax, schema, filename mismatch, duplicate type)\n * accumulate into {@link AnalysisIssue}s; no short-circuit.\n * - Never throws. Generator callers abort on `issues.some(i => i.severity === 'error')`.\n */\nexport function loadJobs(jobsDir: string): LoadJobsResult {\n\tconst jobs: JobDefinition[] = [];\n\tconst issues: AnalysisIssue[] = [];\n\n\tconst resolvedDir = resolve(jobsDir);\n\n\tlet files: string[];\n\ttry {\n\t\tfiles = findYamlFiles(resolvedDir);\n\t} catch {\n\t\tissues.push({\n\t\t\tseverity: 'warning',\n\t\t\ttype: 'no_jobs_dir',\n\t\t\tmessage: `No jobs directory found at: ${resolvedDir}`,\n\t\t\tpath: resolvedDir,\n\t\t});\n\t\treturn { jobs, issues };\n\t}\n\n\tif (files.length === 0) {\n\t\tissues.push({\n\t\t\tseverity: 'warning',\n\t\t\ttype: 'no_files',\n\t\t\tmessage: `No job YAML files found in directory: ${resolvedDir}`,\n\t\t\tpath: resolvedDir,\n\t\t});\n\t\treturn { jobs, issues };\n\t}\n\n\tconst seenTypes = new Map<string, string>(); // type → filePath of first definition\n\n\tfor (const filePath of files) {\n\t\tconst result: LoadJobResult = loadJobFromYaml(filePath);\n\n\t\tif (!result.success) {\n\t\t\tissues.push(...loadErrorToIssue(result));\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst { definition } = result;\n\t\tconst baseName = stripYamlExt(filePath);\n\n\t\t// Filename ↔ type match. The job type IS the @JobHandler('<type>')\n\t\t// registry key; a drift between filename and type is a silent footgun.\n\t\tif (baseName !== definition.type) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'error',\n\t\t\t\ttype: 'job_filename_mismatch',\n\t\t\t\tmessage: `Job file '${baseName}' must contain 'type: ${baseName}' (found 'type: ${definition.type}')`,\n\t\t\t\tpath: filePath,\n\t\t\t\tsuggestion: `Rename the file to '${definition.type}.yaml' or fix the 'type' field to '${baseName}'`,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Duplicate type detection (belt-and-braces — filename match usually\n\t\t// prevents this, but defend against symlinks / .yml vs .yaml twins).\n\t\tif (seenTypes.has(definition.type)) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'error',\n\t\t\t\ttype: 'duplicate_job_type',\n\t\t\t\tmessage: `Duplicate job type '${definition.type}' (already declared in ${seenTypes.get(definition.type)})`,\n\t\t\t\tpath: filePath,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\tseenTypes.set(definition.type, filePath);\n\t\tjobs.push(definition);\n\t}\n\n\treturn { jobs, issues };\n}\n","/**\n * Graph Builder\n *\n * Builds a domain graph from parsed entities, including nodes and edges.\n * Tracks bidirectional connections between entities.\n */\n\nimport type {\n\tParsedEntity,\n\tParsedRelationship,\n\tParsedRelationshipDefinition,\n\tDomainGraph,\n\tRelationshipEdge,\n\tEntityNode,\n} from './types';\n\n/**\n * Infer cardinality from relationship type\n */\nfunction inferCardinality(type: string): '1:1' | '1:N' | 'N:1' | 'N:M' {\n\tswitch (type) {\n\t\tcase 'belongs_to':\n\t\t\treturn 'N:1';\n\t\tcase 'has_many':\n\t\t\treturn '1:N';\n\t\tcase 'has_one':\n\t\t\treturn '1:1';\n\t\tdefault:\n\t\t\treturn '1:N';\n\t}\n}\n\n/**\n * Check if an edge already exists in the opposite direction\n */\nfunction hasReverseEdge(\n\tedges: RelationshipEdge[],\n\tfrom: string,\n\tto: string\n): RelationshipEdge | undefined {\n\treturn edges.find((e) => e.from === to && e.to === from);\n}\n\n/**\n * Build a domain graph from parsed entities\n */\nexport function buildDomainGraph(\n\tentities: ParsedEntity[],\n\trelationshipDefinitions: ParsedRelationshipDefinition[] = [],\n): DomainGraph {\n\tconst entityMap = new Map<string, ParsedEntity>();\n\tconst relDefMap = new Map<string, ParsedRelationshipDefinition>();\n\tconst edges: RelationshipEdge[] = [];\n\n\t// Build entity map\n\tfor (const entity of entities) {\n\t\tentityMap.set(entity.name, entity);\n\t}\n\n\t// Build relationship definition map\n\tfor (const relDef of relationshipDefinitions) {\n\t\trelDefMap.set(relDef.name, relDef);\n\t}\n\n\t// Build edges from inline entity relationships (belongs_to, has_many, has_one)\n\tfor (const entity of entities) {\n\t\tfor (const [relName, rel] of entity.relationships) {\n\t\t\tif (!rel.resolved) continue;\n\n\t\t\t// Check if reverse edge already exists\n\t\t\tconst reverseEdge = hasReverseEdge(edges, entity.name, rel.target);\n\n\t\t\tconst edge: RelationshipEdge = {\n\t\t\t\tfrom: entity.name,\n\t\t\t\tto: rel.target,\n\t\t\t\trelationship: rel,\n\t\t\t\tcardinality: inferCardinality(rel.type),\n\t\t\t\tbidirectional: reverseEdge !== undefined,\n\t\t\t};\n\n\t\t\t// Mark reverse edge as bidirectional too\n\t\t\tif (reverseEdge) {\n\t\t\t\treverseEdge.bidirectional = true;\n\t\t\t}\n\n\t\t\tedges.push(edge);\n\t\t}\n\t}\n\n\t// Build edges from first-class relationship definitions (junction entities)\n\tfor (const relDef of relationshipDefinitions) {\n\t\tconst fromExists = entityMap.has(relDef.from);\n\t\tconst toExists = entityMap.has(relDef.to);\n\n\t\tif (fromExists && toExists) {\n\t\t\t// Create an N:M edge — junction tables are always many-to-many\n\t\t\tconst edge: RelationshipEdge = {\n\t\t\t\tfrom: relDef.from,\n\t\t\t\tto: relDef.to,\n\t\t\t\trelationship: {\n\t\t\t\t\tname: relDef.name,\n\t\t\t\t\ttype: 'has_many',\n\t\t\t\t\ttarget: relDef.to,\n\t\t\t\t\tforeignKey: relDef.fromColumn,\n\t\t\t\t\tresolved: true,\n\t\t\t\t},\n\t\t\t\tcardinality: 'N:M',\n\t\t\t\tbidirectional: relDef.types.some((t) => t.bidirectional),\n\t\t\t};\n\n\t\t\tedges.push(edge);\n\t\t}\n\t}\n\n\treturn { entities: entityMap, relationshipDefinitions: relDefMap, edges };\n}\n\n/**\n * Get all entities related to a given entity within a specified depth\n */\nexport function getRelatedEntities(\n\tgraph: DomainGraph,\n\tentityName: string,\n\tdepth = 1\n): Set<string> {\n\tconst related = new Set<string>();\n\tconst visited = new Set<string>();\n\tconst queue: Array<{ name: string; currentDepth: number }> = [\n\t\t{ name: entityName, currentDepth: 0 },\n\t];\n\n\twhile (queue.length > 0) {\n\t\tconst item = queue.shift();\n\t\tif (!item) continue;\n\n\t\tconst { name, currentDepth } = item;\n\t\tif (visited.has(name) || currentDepth > depth) continue;\n\t\tvisited.add(name);\n\n\t\tfor (const edge of graph.edges) {\n\t\t\tif (edge.from === name && !visited.has(edge.to)) {\n\t\t\t\trelated.add(edge.to);\n\t\t\t\tqueue.push({ name: edge.to, currentDepth: currentDepth + 1 });\n\t\t\t}\n\t\t\tif (edge.to === name && !visited.has(edge.from)) {\n\t\t\t\trelated.add(edge.from);\n\t\t\t\tqueue.push({ name: edge.from, currentDepth: currentDepth + 1 });\n\t\t\t}\n\t\t}\n\t}\n\n\treturn related;\n}\n\n/**\n * Find entities with no relationships (orphans)\n */\nexport function findOrphanEntities(graph: DomainGraph): string[] {\n\tconst orphans: string[] = [];\n\tfor (const [name] of graph.entities) {\n\t\tconst hasRelationship = graph.edges.some((e) => e.from === name || e.to === name);\n\t\tif (!hasRelationship) {\n\t\t\torphans.push(name);\n\t\t}\n\t}\n\treturn orphans;\n}\n\n/**\n * Find circular dependencies in the graph\n */\nexport function findCircularDependencies(graph: DomainGraph): string[][] {\n\tconst cycles: string[][] = [];\n\tconst visited = new Set<string>();\n\tconst recursionStack = new Set<string>();\n\n\tfunction dfs(node: string, path: string[]): void {\n\t\tvisited.add(node);\n\t\trecursionStack.add(node);\n\n\t\tconst outgoingEdges = graph.edges.filter((e) => e.from === node);\n\t\tfor (const edge of outgoingEdges) {\n\t\t\tif (!visited.has(edge.to)) {\n\t\t\t\tdfs(edge.to, [...path, edge.to]);\n\t\t\t} else if (recursionStack.has(edge.to)) {\n\t\t\t\t// Found cycle\n\t\t\t\tconst cycleStart = path.indexOf(edge.to);\n\t\t\t\tif (cycleStart !== -1) {\n\t\t\t\t\tcycles.push([...path.slice(cycleStart), edge.to]);\n\t\t\t\t} else {\n\t\t\t\t\t// The cycle starts at edge.to which is in the recursion stack\n\t\t\t\t\tcycles.push([...path, edge.to]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\trecursionStack.delete(node);\n\t}\n\n\tfor (const [name] of graph.entities) {\n\t\tif (!visited.has(name)) {\n\t\t\tdfs(name, [name]);\n\t\t}\n\t}\n\n\t// Deduplicate cycles (same cycle can be detected from different starting points)\n\tconst uniqueCycles: string[][] = [];\n\tconst seen = new Set<string>();\n\n\tfor (const cycle of cycles) {\n\t\t// Normalize cycle by rotating to start with smallest element\n\t\tconst minIndex = cycle.indexOf(\n\t\t\tcycle.reduce((min, val) => (val < min ? val : min), cycle[0])\n\t\t);\n\t\tconst normalized = [...cycle.slice(minIndex), ...cycle.slice(0, minIndex)];\n\t\tconst key = normalized.join('->');\n\n\t\tif (!seen.has(key)) {\n\t\t\tseen.add(key);\n\t\t\tuniqueCycles.push(cycle);\n\t\t}\n\t}\n\n\treturn uniqueCycles;\n}\n\n/**\n * Build entity nodes for visualization\n */\nexport function buildEntityNodes(graph: DomainGraph): EntityNode[] {\n\tconst nodes: EntityNode[] = [];\n\tfor (const [name, entity] of graph.entities) {\n\t\tnodes.push({\n\t\t\tid: name,\n\t\t\tname: entity.name,\n\t\t\tentity,\n\t\t});\n\t}\n\treturn nodes;\n}\n","/**\n * External ID Tracking Behavior\n *\n * Adds external_id, provider, and provider_metadata fields to track\n * records that are synced from external systems (e.g., Salesforce, HubSpot).\n */\n\nimport type { BehaviorDefinition } from './types';\n\nexport const externalIdTrackingBehavior: BehaviorDefinition = {\n\tname: 'external_id_tracking',\n\tdescription: 'Adds external_id, provider, and provider_metadata fields for external system sync tracking',\n\n\tfields: [\n\t\t{\n\t\t\tname: 'external_id',\n\t\t\tcamelName: 'externalId',\n\t\t\ttype: 'string',\n\t\t\ttsType: 'string | null',\n\t\t\tdrizzleType: 'varchar',\n\t\t\tdrizzleImports: ['varchar', 'index'],\n\t\t\tzodType: 'z.string().nullable()',\n\t\t\tnullable: true,\n\t\t\tui: {\n\t\t\t\tlabel: 'External ID',\n\t\t\t\ttype: 'text',\n\t\t\t\timportance: 'tertiary',\n\t\t\t\tgroup: 'metadata',\n\t\t\t\tvisible: false,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: 'provider',\n\t\t\tcamelName: 'provider',\n\t\t\ttype: 'string',\n\t\t\ttsType: 'string | null',\n\t\t\tdrizzleType: 'varchar',\n\t\t\tdrizzleImports: ['varchar'],\n\t\t\tzodType: 'z.string().nullable()',\n\t\t\tnullable: true,\n\t\t\tui: {\n\t\t\t\tlabel: 'Provider',\n\t\t\t\ttype: 'text',\n\t\t\t\timportance: 'tertiary',\n\t\t\t\tgroup: 'metadata',\n\t\t\t\tvisible: false,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: 'provider_metadata',\n\t\t\tcamelName: 'providerMetadata',\n\t\t\ttype: 'json',\n\t\t\ttsType: 'unknown | null',\n\t\t\tdrizzleType: 'jsonb',\n\t\t\tdrizzleImports: ['jsonb'],\n\t\t\tzodType: 'z.unknown().nullable()',\n\t\t\tnullable: true,\n\t\t\tui: {\n\t\t\t\tlabel: 'Provider Metadata',\n\t\t\t\ttype: 'json',\n\t\t\t\timportance: 'tertiary',\n\t\t\t\tgroup: 'metadata',\n\t\t\t\tvisible: false,\n\t\t\t},\n\t\t},\n\t],\n\n\tdrizzleImports: ['varchar', 'jsonb', 'index'],\n\n\tconfigKey: 'externalIdTracking',\n};\n","/**\n * Soft Delete Behavior\n *\n * Adds deleted_at field for soft delete functionality.\n * Records are marked as deleted instead of being removed from the database.\n * BaseRepository automatically filters soft-deleted records in queries.\n */\n\nimport type { BehaviorDefinition } from './types';\n\nexport const softDeleteBehavior: BehaviorDefinition = {\n\tname: 'soft_delete',\n\tdescription: 'Adds deleted_at field for soft delete functionality',\n\n\tfields: [\n\t\t{\n\t\t\tname: 'deleted_at',\n\t\t\tcamelName: 'deletedAt',\n\t\t\ttype: 'datetime',\n\t\t\ttsType: 'Date | null',\n\t\t\tdrizzleType: 'timestamp',\n\t\t\tdrizzleImports: ['timestamp'],\n\t\t\tzodType: 'z.coerce.date().nullable()',\n\t\t\tnullable: true,\n\t\t\tui: {\n\t\t\t\tlabel: 'Deleted At',\n\t\t\t\ttype: 'datetime',\n\t\t\t\timportance: 'tertiary',\n\t\t\t\tgroup: 'metadata',\n\t\t\t\tvisible: false,\n\t\t\t},\n\t\t},\n\t],\n\n\tdrizzleImports: ['timestamp'],\n\n\tmethods: [\n\t\t'softDelete',\n\t\t'restore',\n\t\t'findWithDeleted',\n\t\t'findOnlyDeleted',\n\t\t'baseQuery', // Modified to filter deleted records\n\t],\n\n\tconfigKey: 'softDelete',\n};\n","/**\n * Timestamps Behavior\n *\n * Adds created_at and updated_at fields to track entity lifecycle.\n * These fields are automatically managed by BaseRepository.\n */\n\nimport type { BehaviorDefinition } from './types';\n\nexport const timestampsBehavior: BehaviorDefinition = {\n\tname: 'timestamps',\n\tdescription: 'Adds created_at and updated_at timestamp fields',\n\n\tfields: [\n\t\t{\n\t\t\tname: 'created_at',\n\t\t\tcamelName: 'createdAt',\n\t\t\ttype: 'datetime',\n\t\t\ttsType: 'Date',\n\t\t\tdrizzleType: 'timestamp',\n\t\t\tdrizzleImports: ['timestamp'],\n\t\t\tzodType: 'z.coerce.date()',\n\t\t\tnullable: false,\n\t\t\tdefault: 'now()',\n\t\t\tui: {\n\t\t\t\tlabel: 'Created At',\n\t\t\t\ttype: 'datetime',\n\t\t\t\timportance: 'tertiary',\n\t\t\t\tgroup: 'metadata',\n\t\t\t\tvisible: false,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: 'updated_at',\n\t\t\tcamelName: 'updatedAt',\n\t\t\ttype: 'datetime',\n\t\t\ttsType: 'Date',\n\t\t\tdrizzleType: 'timestamp',\n\t\t\tdrizzleImports: ['timestamp'],\n\t\t\tzodType: 'z.coerce.date()',\n\t\t\tnullable: false,\n\t\t\tdefault: 'now()',\n\t\t\tui: {\n\t\t\t\tlabel: 'Updated At',\n\t\t\t\ttype: 'datetime',\n\t\t\t\timportance: 'tertiary',\n\t\t\t\tgroup: 'metadata',\n\t\t\t\tvisible: false,\n\t\t\t},\n\t\t},\n\t],\n\n\tdrizzleImports: ['timestamp'],\n\n\tmethods: ['applyTimestampsOnCreate', 'applyTimestampsOnUpdate'],\n\n\tconfigKey: 'timestamps',\n};\n","/**\n * User Tracking Behavior\n *\n * Adds created_by and updated_by fields to track which user\n * created and last modified an entity.\n * These fields are automatically managed by BaseRepository when\n * a RepositoryContext with userId is provided.\n */\n\nimport type { BehaviorDefinition } from './types';\n\nexport const userTrackingBehavior: BehaviorDefinition = {\n\tname: 'user_tracking',\n\tdescription: 'Adds created_by and updated_by user reference fields',\n\n\tfields: [\n\t\t{\n\t\t\tname: 'created_by',\n\t\t\tcamelName: 'createdBy',\n\t\t\ttype: 'uuid',\n\t\t\ttsType: 'string | null',\n\t\t\tdrizzleType: 'uuid',\n\t\t\tdrizzleImports: ['uuid'],\n\t\t\tzodType: 'z.string().uuid().nullable()',\n\t\t\tnullable: true,\n\t\t\tforeignKey: 'users.id',\n\t\t\tui: {\n\t\t\t\tlabel: 'Created By',\n\t\t\t\ttype: 'reference',\n\t\t\t\timportance: 'tertiary',\n\t\t\t\tgroup: 'metadata',\n\t\t\t\tvisible: false,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: 'updated_by',\n\t\t\tcamelName: 'updatedBy',\n\t\t\ttype: 'uuid',\n\t\t\ttsType: 'string | null',\n\t\t\tdrizzleType: 'uuid',\n\t\t\tdrizzleImports: ['uuid'],\n\t\t\tzodType: 'z.string().uuid().nullable()',\n\t\t\tnullable: true,\n\t\t\tforeignKey: 'users.id',\n\t\t\tui: {\n\t\t\t\tlabel: 'Updated By',\n\t\t\t\ttype: 'reference',\n\t\t\t\timportance: 'tertiary',\n\t\t\t\tgroup: 'metadata',\n\t\t\t\tvisible: false,\n\t\t\t},\n\t\t},\n\t],\n\n\tdrizzleImports: ['uuid'],\n\n\tmethods: ['applyUserTrackingOnCreate', 'applyUserTrackingOnUpdate'],\n\n\tconfigKey: 'userTracking',\n};\n","/**\n * Behavior Registry - Central registry for all entity behaviors\n *\n * Provides functions to:\n * - Get behavior definitions by name\n * - Validate behavior configurations\n * - Resolve fields added by behaviors\n */\n\nimport { externalIdTrackingBehavior } from './external-id-tracking';\nimport { softDeleteBehavior } from './soft-delete';\nimport { timestampsBehavior } from './timestamps';\nimport type {\n\tBehaviorConfig,\n\tBehaviorDefinition,\n\tBehaviorField,\n\tNormalizedBehaviorConfig,\n\tResolvedBehaviors,\n\tValidationResult,\n} from './types';\nimport { userTrackingBehavior } from './user-tracking';\n\n// ============================================================================\n// Behavior Registry\n// ============================================================================\n\nconst behaviorRegistry = new Map<string, BehaviorDefinition>([\n\t['timestamps', timestampsBehavior],\n\t['soft_delete', softDeleteBehavior],\n\t['user_tracking', userTrackingBehavior],\n\t['external_id_tracking', externalIdTrackingBehavior],\n]);\n\n/**\n * Get a behavior definition by name\n */\nexport function getBehavior(name: string): BehaviorDefinition | undefined {\n\treturn behaviorRegistry.get(name);\n}\n\n/**\n * Get all registered behavior names\n */\nexport function getAllBehaviorNames(): string[] {\n\treturn Array.from(behaviorRegistry.keys());\n}\n\n// ============================================================================\n// Config Normalization\n// ============================================================================\n\n/**\n * Normalize a behavior config to always have name and options\n */\nexport function normalizeBehaviorConfig(\n\tconfig: BehaviorConfig,\n): NormalizedBehaviorConfig {\n\tif (typeof config === 'string') {\n\t\treturn { name: config, options: {} };\n\t}\n\treturn { name: config.name, options: config.options ?? {} };\n}\n\n/**\n * Normalize an array of behavior configs\n */\nexport function normalizeBehaviorConfigs(\n\tconfigs: BehaviorConfig[],\n): NormalizedBehaviorConfig[] {\n\treturn configs.map(normalizeBehaviorConfig);\n}\n\n// ============================================================================\n// Validation\n// ============================================================================\n\n/**\n * Validate a set of behavior configurations\n * Checks for unknown behaviors, missing dependencies, and conflicts\n */\nexport function validateBehaviors(configs: BehaviorConfig[]): ValidationResult {\n\tconst errors: string[] = [];\n\tconst warnings: string[] = [];\n\tconst normalized = normalizeBehaviorConfigs(configs);\n\tconst enabledNames = new Set(normalized.map((c) => c.name));\n\n\tfor (const config of normalized) {\n\t\tconst behavior = getBehavior(config.name);\n\n\t\t// Check behavior exists\n\t\tif (!behavior) {\n\t\t\terrors.push(`Unknown behavior: '${config.name}'`);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Check dependencies\n\t\tif (behavior.requires) {\n\t\t\tfor (const req of behavior.requires) {\n\t\t\t\tif (!enabledNames.has(req)) {\n\t\t\t\t\terrors.push(\n\t\t\t\t\t\t`Behavior '${config.name}' requires '${req}' which is not enabled`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Check conflicts\n\t\tif (behavior.conflicts) {\n\t\t\tfor (const conflict of behavior.conflicts) {\n\t\t\t\tif (enabledNames.has(conflict)) {\n\t\t\t\t\terrors.push(\n\t\t\t\t\t\t`Behavior '${config.name}' conflicts with '${conflict}'`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tvalid: errors.length === 0,\n\t\terrors,\n\t\twarnings,\n\t};\n}\n\n// ============================================================================\n// Field Resolution\n// ============================================================================\n\n/**\n * Get all fields added by a set of behaviors\n */\nexport function resolveBehaviorFields(\n\tconfigs: BehaviorConfig[],\n): BehaviorField[] {\n\tconst normalized = normalizeBehaviorConfigs(configs);\n\tconst fields: BehaviorField[] = [];\n\tconst addedFieldNames = new Set<string>();\n\n\tfor (const config of normalized) {\n\t\tconst behavior = getBehavior(config.name);\n\t\tif (!behavior) continue;\n\n\t\tfor (const field of behavior.fields) {\n\t\t\t// Avoid duplicate fields if multiple behaviors add the same field\n\t\t\tif (!addedFieldNames.has(field.name)) {\n\t\t\t\tfields.push(field);\n\t\t\t\taddedFieldNames.add(field.name);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn fields;\n}\n\n/**\n * Get all Drizzle imports needed by a set of behaviors\n */\nexport function resolveBehaviorDrizzleImports(\n\tconfigs: BehaviorConfig[],\n): string[] {\n\tconst normalized = normalizeBehaviorConfigs(configs);\n\tconst imports = new Set<string>();\n\n\tfor (const config of normalized) {\n\t\tconst behavior = getBehavior(config.name);\n\t\tif (!behavior) continue;\n\n\t\tfor (const imp of behavior.drizzleImports) {\n\t\t\timports.add(imp);\n\t\t}\n\t}\n\n\treturn Array.from(imports).sort();\n}\n\n// ============================================================================\n// Full Resolution\n// ============================================================================\n\n/**\n * Resolve all behavior data for templates\n */\nexport function resolveBehaviors(configs: BehaviorConfig[]): ResolvedBehaviors {\n\tconst normalized = normalizeBehaviorConfigs(configs);\n\tconst fields = resolveBehaviorFields(configs);\n\tconst drizzleImports = resolveBehaviorDrizzleImports(configs);\n\n\tconst enabledNames = new Set(normalized.map((c) => c.name));\n\n\tconst hasTimestamps = enabledNames.has('timestamps');\n\tconst hasSoftDelete = enabledNames.has('soft_delete');\n\tconst hasUserTracking = enabledNames.has('user_tracking');\n\tconst hasExternalIdTracking = enabledNames.has('external_id_tracking');\n\n\treturn {\n\t\tconfigs: normalized,\n\t\tfields,\n\t\tdrizzleImports,\n\t\trepositoryConfig: {\n\t\t\ttimestamps: hasTimestamps,\n\t\t\tsoftDelete: hasSoftDelete,\n\t\t\tuserTracking: hasUserTracking,\n\t\t\tversionable: false, // Future behavior\n\t\t},\n\t\thasBehaviors: normalized.length > 0,\n\t\thasTimestamps,\n\t\thasSoftDelete,\n\t\thasUserTracking,\n\t\thasExternalIdTracking,\n\t};\n}\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport type {\n\tBehaviorConfig,\n\tBehaviorDefinition,\n\tBehaviorField,\n\tNormalizedBehaviorConfig,\n\tResolvedBehaviors,\n\tValidationResult,\n} from './types';\n\nexport { timestampsBehavior } from './timestamps';\nexport { softDeleteBehavior } from './soft-delete';\nexport { userTrackingBehavior } from './user-tracking';\nexport { externalIdTrackingBehavior } from './external-id-tracking';\n","/**\n * Consistency Checker\n *\n * Performs various consistency checks on the domain model:\n * - Missing relationship targets\n * - Missing inverse relationships\n * - Missing indexes on filterable fields\n * - Orphan entities (no relationships)\n * - Circular dependencies\n * - Naming conventions\n * - Missing UI metadata\n */\n\nimport type { ParsedEntity, DomainGraph, AnalysisIssue } from './types';\nimport { findOrphanEntities, findCircularDependencies } from './graph-builder';\nimport { resolveBehaviorFields } from '../behaviors/index';\n\n/**\n * Run all consistency checks on the domain graph\n */\nexport function checkConsistency(graph: DomainGraph): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\t// Check each entity\n\tfor (const [name, entity] of graph.entities) {\n\t\tissues.push(...checkEntityConsistency(entity));\n\t\tissues.push(...checkRelationshipConsistency(entity, graph));\n\t\tissues.push(...checkNamingConventions(entity));\n\t\tissues.push(...checkMissingIndexes(entity));\n\t\tissues.push(...checkUiMetadata(entity));\n\t\tif (entity.queries !== undefined) {\n\t\t\tissues.push(...checkQueryFieldReferences(entity));\n\t\t}\n\t\tif (entity.integration !== undefined) {\n\t\t\tissues.push(...checkIntegrationFieldMappingReferences(entity));\n\t\t\tissues.push(...checkExternalIdTrackingCollision(entity));\n\t\t}\n\t}\n\n\t// Check graph-level issues\n\tissues.push(...checkOrphanEntities(graph));\n\tissues.push(...checkCircularReferences(graph));\n\tissues.push(...checkMissingInverses(graph));\n\n\treturn issues;\n}\n\n/**\n * Check entity-level consistency\n */\nfunction checkEntityConsistency(entity: ParsedEntity): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\t// Check for missing primary key\n\tif (!entity.fields.has('id')) {\n\t\tissues.push({\n\t\t\tseverity: 'info',\n\t\t\ttype: 'missing_id',\n\t\t\tentity: entity.name,\n\t\t\tmessage: 'Entity missing standard \"id\" field',\n\t\t\tsuggestion: 'Add an \"id\" field with type \"uuid\"',\n\t\t});\n\t}\n\n\t// Check for missing timestamps\n\tconst hasCreatedAt = entity.fields.has('created_at');\n\tconst hasTimestampsBehavior = entity.behaviors.includes('timestamps');\n\n\tif (!hasCreatedAt && !hasTimestampsBehavior) {\n\t\tissues.push({\n\t\t\tseverity: 'info',\n\t\t\ttype: 'missing_timestamps',\n\t\t\tentity: entity.name,\n\t\t\tmessage: 'Entity missing \"created_at\" field and \"timestamps\" behavior',\n\t\t\tsuggestion: 'Add \"timestamps\" to behaviors or add created_at/updated_at fields',\n\t\t});\n\t}\n\n\treturn issues;\n}\n\n/**\n * Check relationship consistency\n */\nfunction checkRelationshipConsistency(\n\tentity: ParsedEntity,\n\tgraph: DomainGraph\n): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\tfor (const [relName, rel] of entity.relationships) {\n\t\t// Check for belongs_to without matching foreign key field\n\t\tif (rel.type === 'belongs_to') {\n\t\t\tconst fkField = entity.fields.get(rel.foreignKey);\n\t\t\tif (!fkField) {\n\t\t\t\tissues.push({\n\t\t\t\t\tseverity: 'warning',\n\t\t\t\t\ttype: 'missing_fk_field',\n\t\t\t\t\tentity: entity.name,\n\t\t\t\t\tfield: relName,\n\t\t\t\t\tmessage: `Relationship \"${relName}\" references foreign key \"${rel.foreignKey}\" but field doesn't exist`,\n\t\t\t\t\tsuggestion: `Add field \"${rel.foreignKey}\" with foreign_key reference`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Check for has_many relationships - target should have the FK field\n\t\tif (rel.type === 'has_many' || rel.type === 'has_one') {\n\t\t\tconst targetEntity = graph.entities.get(rel.target);\n\t\t\tif (targetEntity) {\n\t\t\t\tconst targetFkField = targetEntity.fields.get(rel.foreignKey);\n\t\t\t\tif (!targetFkField) {\n\t\t\t\t\tissues.push({\n\t\t\t\t\t\tseverity: 'warning',\n\t\t\t\t\t\ttype: 'missing_target_fk',\n\t\t\t\t\t\tentity: entity.name,\n\t\t\t\t\t\tfield: relName,\n\t\t\t\t\t\tmessage: `Relationship \"${relName}\" expects foreign key \"${rel.foreignKey}\" on \"${rel.target}\" but field doesn't exist`,\n\t\t\t\t\t\tsuggestion: `Add field \"${rel.foreignKey}\" to \"${rel.target}\" entity`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n/**\n * Check naming conventions\n */\nfunction checkNamingConventions(entity: ParsedEntity): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\t// Entity name should be lowercase snake_case\n\tif (entity.name !== entity.name.toLowerCase()) {\n\t\tissues.push({\n\t\t\tseverity: 'warning',\n\t\t\ttype: 'naming_convention',\n\t\t\tentity: entity.name,\n\t\t\tmessage: 'Entity name should be lowercase',\n\t\t\tsuggestion: `Use \"${entity.name.toLowerCase()}\"`,\n\t\t});\n\t}\n\n\t// Check field naming\n\tfor (const [fieldName] of entity.fields) {\n\t\tif (fieldName !== fieldName.toLowerCase()) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'warning',\n\t\t\t\ttype: 'naming_convention',\n\t\t\t\tentity: entity.name,\n\t\t\t\tfield: fieldName,\n\t\t\t\tmessage: 'Field name should be snake_case',\n\t\t\t\tsuggestion: `Use \"${toSnakeCase(fieldName)}\"`,\n\t\t\t});\n\t\t}\n\t}\n\n\t// Check relationship naming\n\tfor (const [relName] of entity.relationships) {\n\t\tif (relName !== relName.toLowerCase()) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'warning',\n\t\t\t\ttype: 'naming_convention',\n\t\t\t\tentity: entity.name,\n\t\t\t\tfield: relName,\n\t\t\t\tmessage: 'Relationship name should be snake_case',\n\t\t\t\tsuggestion: `Use \"${toSnakeCase(relName)}\"`,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n/**\n * Check for missing indexes on filterable fields\n */\nfunction checkMissingIndexes(entity: ParsedEntity): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\tfor (const [fieldName, field] of entity.fields) {\n\t\t// Check if field is marked as filterable but has no index\n\t\tif (field.ui.filterable && !field.index && !field.unique) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'warning',\n\t\t\t\ttype: 'missing_index',\n\t\t\t\tentity: entity.name,\n\t\t\t\tfield: fieldName,\n\t\t\t\tmessage: `Field \"${fieldName}\" is filterable but has no index`,\n\t\t\t\tsuggestion: 'Add \"index: true\" to improve query performance',\n\t\t\t});\n\t\t}\n\n\t\t// Foreign key fields should typically have an index\n\t\tif (field.foreignKey && !field.index && !field.unique) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'info',\n\t\t\t\ttype: 'missing_fk_index',\n\t\t\t\tentity: entity.name,\n\t\t\t\tfield: fieldName,\n\t\t\t\tmessage: `Foreign key field \"${fieldName}\" has no index`,\n\t\t\t\tsuggestion: 'Add \"index: true\" for better join performance',\n\t\t\t});\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n/**\n * Check for missing UI metadata\n */\nfunction checkUiMetadata(entity: ParsedEntity): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\t// System fields that don't need UI metadata\n\tconst systemFields = new Set(['id', 'created_at', 'updated_at', 'deleted_at', 'tenant_id']);\n\n\tfor (const [fieldName, field] of entity.fields) {\n\t\tif (systemFields.has(fieldName)) continue;\n\n\t\tconst hasAnyUiMeta =\n\t\t\tfield.ui.label !== undefined ||\n\t\t\tfield.ui.type !== undefined ||\n\t\t\tfield.ui.group !== undefined;\n\n\t\tif (!hasAnyUiMeta) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'info',\n\t\t\t\ttype: 'missing_ui_metadata',\n\t\t\t\tentity: entity.name,\n\t\t\t\tfield: fieldName,\n\t\t\t\tmessage: `Field \"${fieldName}\" has no UI metadata`,\n\t\t\t\tsuggestion: 'Add ui_label, ui_type, ui_group for better admin panel display',\n\t\t\t});\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n/**\n * Check for orphan entities\n */\nfunction checkOrphanEntities(graph: DomainGraph): AnalysisIssue[] {\n\tconst orphans = findOrphanEntities(graph);\n\treturn orphans.map((name) => ({\n\t\tseverity: 'info' as const,\n\t\ttype: 'orphan_entity',\n\t\tentity: name,\n\t\tmessage: `Entity \"${name}\" has no relationships to other entities`,\n\t\tsuggestion: 'Consider if this entity should be related to others',\n\t}));\n}\n\n/**\n * Check for circular references\n */\nfunction checkCircularReferences(graph: DomainGraph): AnalysisIssue[] {\n\tconst cycles = findCircularDependencies(graph);\n\treturn cycles.map((cycle) => ({\n\t\tseverity: 'info' as const,\n\t\ttype: 'circular_dependency',\n\t\tentity: cycle[0],\n\t\tmessage: `Circular reference detected: ${cycle.join(' -> ')}`,\n\t\tsuggestion: 'Verify this is intentional (e.g., self-referential hierarchy)',\n\t}));\n}\n\n/**\n * Check for missing inverse relationships\n */\nfunction checkMissingInverses(graph: DomainGraph): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\tfor (const edge of graph.edges) {\n\t\tconst { from, to, relationship } = edge;\n\t\tconst targetEntity = graph.entities.get(to);\n\t\tif (!targetEntity) continue;\n\n\t\t// Check if target has an inverse relationship back to source\n\t\tconst hasInverse = Array.from(targetEntity.relationships.values()).some(\n\t\t\t(rel) => rel.target === from\n\t\t);\n\n\t\t// belongs_to relationships typically don't need explicit inverses\n\t\t// (the has_many on the other side serves as the inverse)\n\t\tif (!hasInverse && relationship.type !== 'belongs_to') {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'info',\n\t\t\t\ttype: 'missing_inverse',\n\t\t\t\tentity: from,\n\t\t\t\tfield: relationship.name,\n\t\t\t\tmessage: `Relationship \"${relationship.name}\" to \"${to}\" has no inverse defined on target`,\n\t\t\t\tsuggestion: `Add inverse relationship on \"${to}\" pointing back to \"${from}\"`,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n/**\n * Get the set of all valid field names for an entity, including behavior-added fields\n * and belongs_to foreign key fields (which the template emits as columns even when\n * not explicitly declared under `fields:`).\n */\nfunction getAvailableFieldNames(entity: ParsedEntity): string[] {\n\tconst entityFieldNames = Array.from(entity.fields.keys());\n\tconst behaviorFields = resolveBehaviorFields(entity.behaviors);\n\tconst behaviorFieldNames = behaviorFields.map((f) => f.name);\n\tconst belongsToFkNames: string[] = [];\n\tfor (const rel of entity.relationships.values()) {\n\t\tif (rel.type === 'belongs_to' && rel.foreignKey) {\n\t\t\tbelongsToFkNames.push(rel.foreignKey);\n\t\t}\n\t}\n\treturn [...new Set([...entityFieldNames, ...behaviorFieldNames, ...belongsToFkNames])];\n}\n\n/**\n * Check that query.by and query.select fields reference existing entity fields\n */\nfunction checkQueryFieldReferences(entity: ParsedEntity): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\tconst availableFields = getAvailableFieldNames(entity);\n\tconst availableSet = new Set(availableFields);\n\n\tfor (const query of entity.queries ?? []) {\n\t\t// Skip by-field validation when via is specified — those fields come from the junction table\n\t\tif (!query.via) {\n\t\t\tfor (const fieldName of query.by) {\n\t\t\t\tif (!availableSet.has(fieldName)) {\n\t\t\t\t\tissues.push({\n\t\t\t\t\t\tseverity: 'error',\n\t\t\t\t\t\ttype: 'unknown_query_field',\n\t\t\t\t\t\tentity: entity.name,\n\t\t\t\t\t\tfield: fieldName,\n\t\t\t\t\t\tmessage: `Query references unknown field \"${fieldName}\" in entity \"${entity.name}\". Available fields: ${availableFields.join(', ')}`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (const fieldName of query.select ?? []) {\n\t\t\tif (!availableSet.has(fieldName)) {\n\t\t\t\tissues.push({\n\t\t\t\t\tseverity: 'error',\n\t\t\t\t\ttype: 'unknown_query_field',\n\t\t\t\t\tentity: entity.name,\n\t\t\t\t\tfield: fieldName,\n\t\t\t\t\tmessage: `Query references unknown field \"${fieldName}\" in entity \"${entity.name}\". Available fields: ${availableFields.join(', ')}`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n/**\n * Check that integration field_mapping keys and read_only_fields reference existing entity fields\n */\nfunction checkIntegrationFieldMappingReferences(entity: ParsedEntity): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\tconst availableFields = getAvailableFieldNames(entity);\n\tconst availableSet = new Set(availableFields);\n\n\tfor (const [providerName, provider] of Object.entries(entity.integration?.providers ?? {})) {\n\t\tfor (const fieldName of Object.keys(provider.fieldMapping ?? {})) {\n\t\t\tif (!availableSet.has(fieldName)) {\n\t\t\t\tissues.push({\n\t\t\t\t\tseverity: 'warning',\n\t\t\t\t\ttype: 'unknown_integration_field_mapping',\n\t\t\t\t\tentity: entity.name,\n\t\t\t\t\tfield: fieldName,\n\t\t\t\t\tmessage: `Integration field mapping references unknown field \"${fieldName}\" for provider \"${providerName}\" in entity \"${entity.name}\"`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tfor (const fieldName of provider.readOnlyFields ?? []) {\n\t\t\tif (!availableSet.has(fieldName)) {\n\t\t\t\tissues.push({\n\t\t\t\t\tseverity: 'warning',\n\t\t\t\t\ttype: 'unknown_integration_field_mapping',\n\t\t\t\t\tentity: entity.name,\n\t\t\t\t\tfield: fieldName,\n\t\t\t\t\tmessage: `Integration field mapping references unknown field \"${fieldName}\" for provider \"${providerName}\" in entity \"${entity.name}\"`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n/**\n * Check for potential collision between external_id_tracking behavior and integration field_mapping\n */\nfunction checkExternalIdTrackingCollision(entity: ParsedEntity): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\tconst hasExternalIdTracking = entity.behaviors.includes('external_id_tracking');\n\tif (!hasExternalIdTracking) return issues;\n\n\tfor (const [providerName, provider] of Object.entries(entity.integration?.providers ?? {})) {\n\t\tif (provider.fieldMapping && 'external_id' in provider.fieldMapping) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'warning',\n\t\t\t\ttype: 'external_id_tracking_collision',\n\t\t\t\tentity: entity.name,\n\t\t\t\tfield: 'external_id',\n\t\t\t\tmessage: `Entity \"${entity.name}\" has external_id_tracking behavior and also maps \"external_id\" in integration field_mapping for provider \"${providerName}\". The behavior-added field may collide with the mapped field.`,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n/**\n * Convert string to snake_case\n */\nfunction toSnakeCase(str: string): string {\n\treturn str\n\t\t.replace(/([A-Z])/g, '_$1')\n\t\t.toLowerCase()\n\t\t.replace(/^_/, '');\n}\n","/**\n * Statistics\n *\n * Computes statistics about the domain model:\n * - Entity counts\n * - Field counts and type distribution\n * - Relationship counts and type distribution\n */\n\nimport type { ParsedEntity, DomainGraph, DomainStatistics } from './types';\n\n/**\n * Compute domain statistics from the graph\n */\nexport function computeStatistics(graph: DomainGraph): DomainStatistics {\n\tconst entities = Array.from(graph.entities.values());\n\n\tconst fieldsByType: Record<string, number> = {};\n\tconst relationshipsByType: Record<string, number> = {};\n\tlet totalFields = 0;\n\tlet totalRelationships = 0;\n\tlet entitiesWithBehaviors = 0;\n\n\tfor (const entity of entities) {\n\t\ttotalFields += entity.fields.size;\n\t\ttotalRelationships += entity.relationships.size;\n\n\t\tif (entity.behaviors.length > 0) {\n\t\t\tentitiesWithBehaviors++;\n\t\t}\n\n\t\t// Count fields by type\n\t\tfor (const field of entity.fields.values()) {\n\t\t\tfieldsByType[field.type] = (fieldsByType[field.type] ?? 0) + 1;\n\t\t}\n\n\t\t// Count relationships by type\n\t\tfor (const rel of entity.relationships.values()) {\n\t\t\trelationshipsByType[rel.type] = (relationshipsByType[rel.type] ?? 0) + 1;\n\t\t}\n\t}\n\n\treturn {\n\t\ttotalEntities: entities.length,\n\t\ttotalFields,\n\t\ttotalRelationships,\n\t\tfieldsByType,\n\t\trelationshipsByType,\n\t\tentitiesWithBehaviors,\n\t\taverageFieldsPerEntity: entities.length > 0 ? totalFields / entities.length : 0,\n\t};\n}\n\n/**\n * Get a breakdown of field properties\n */\nexport function getFieldBreakdown(graph: DomainGraph): {\n\trequired: number;\n\tnullable: number;\n\tindexed: number;\n\tunique: number;\n\twithForeignKey: number;\n\twithConstraints: number;\n} {\n\tlet required = 0;\n\tlet nullable = 0;\n\tlet indexed = 0;\n\tlet unique = 0;\n\tlet withForeignKey = 0;\n\tlet withConstraints = 0;\n\n\tfor (const entity of graph.entities.values()) {\n\t\tfor (const field of entity.fields.values()) {\n\t\t\tif (field.required) required++;\n\t\t\tif (field.nullable) nullable++;\n\t\t\tif (field.index) indexed++;\n\t\t\tif (field.unique) unique++;\n\t\t\tif (field.foreignKey) withForeignKey++;\n\n\t\t\tconst hasConstraints =\n\t\t\t\tfield.constraints.minLength !== undefined ||\n\t\t\t\tfield.constraints.maxLength !== undefined ||\n\t\t\t\tfield.constraints.min !== undefined ||\n\t\t\t\tfield.constraints.max !== undefined;\n\t\t\tif (hasConstraints) withConstraints++;\n\t\t}\n\t}\n\n\treturn { required, nullable, indexed, unique, withForeignKey, withConstraints };\n}\n\n/**\n * Get UI metadata coverage statistics\n */\nexport function getUiMetadataCoverage(graph: DomainGraph): {\n\twithLabel: number;\n\twithType: number;\n\twithGroup: number;\n\twithImportance: number;\n\ttotal: number;\n} {\n\tlet withLabel = 0;\n\tlet withType = 0;\n\tlet withGroup = 0;\n\tlet withImportance = 0;\n\tlet total = 0;\n\n\tfor (const entity of graph.entities.values()) {\n\t\tfor (const field of entity.fields.values()) {\n\t\t\ttotal++;\n\t\t\tif (field.ui.label) withLabel++;\n\t\t\tif (field.ui.type) withType++;\n\t\t\tif (field.ui.group) withGroup++;\n\t\t\tif (field.ui.importance) withImportance++;\n\t\t}\n\t}\n\n\treturn { withLabel, withType, withGroup, withImportance, total };\n}\n","/**\n * Transitive Relationship Suggester\n *\n * Detects potential transitive relationships in the domain graph.\n * Uses BFS to find 2-3 hop paths through has_many relationships and\n * generates ready-to-paste YAML snippets for the entity definition files.\n */\n\nimport type {\n\tDomainGraph,\n\tParsedEntity,\n\tParsedRelationship,\n\tTransitiveSuggestion,\n\tTransitivePath,\n\tPathHop,\n} from './types';\n\nexport interface SuggesterOptions {\n\tmaxDepth?: number;\n\texcludeEntities?: string[];\n\texcludePatterns?: RegExp[];\n}\n\nconst DEFAULT_OPTIONS: Required<SuggesterOptions> = {\n\tmaxDepth: 3,\n\texcludeEntities: ['workspace', 'tenant'],\n\texcludePatterns: [/_audit$/, /_log$/, /_history$/],\n};\n\ninterface BFSNode {\n\tentity: string;\n\tdepth: number;\n\tpath: PathHop[];\n\tvisited: Set<string>;\n}\n\n/**\n * Suggest transitive relationships based on graph analysis\n */\nexport function suggestTransitiveRelationships(\n\tgraph: DomainGraph,\n\toptions?: SuggesterOptions\n): TransitiveSuggestion[] {\n\tconst opts = { ...DEFAULT_OPTIONS, ...options };\n\tconst suggestions: TransitiveSuggestion[] = [];\n\n\t// Process each entity as a potential source\n\tfor (const [entityName, entity] of graph.entities) {\n\t\tif (shouldExcludeEntity(entityName, opts)) continue;\n\n\t\tconst paths = findTransitivePaths(graph, entityName, opts);\n\t\tfor (const path of paths) {\n\t\t\tsuggestions.push(createSuggestion(path));\n\t\t}\n\t}\n\n\treturn suggestions;\n}\n\n/**\n * Check if entity should be excluded from analysis\n */\nfunction shouldExcludeEntity(\n\tentityName: string,\n\topts: Required<SuggesterOptions>\n): boolean {\n\t// Check exclude list\n\tif (opts.excludeEntities.includes(entityName)) {\n\t\treturn true;\n\t}\n\n\t// Check exclude patterns\n\tfor (const pattern of opts.excludePatterns) {\n\t\tif (pattern.test(entityName)) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\n/**\n * Find all valid transitive paths from a source entity using BFS\n */\nfunction findTransitivePaths(\n\tgraph: DomainGraph,\n\tsourceEntity: string,\n\topts: Required<SuggesterOptions>\n): TransitivePath[] {\n\tconst paths: TransitivePath[] = [];\n\tconst sourceEntityData = graph.entities.get(sourceEntity);\n\tif (!sourceEntityData) return paths;\n\n\tconst queue: BFSNode[] = [\n\t\t{\n\t\t\tentity: sourceEntity,\n\t\t\tdepth: 0,\n\t\t\tpath: [],\n\t\t\tvisited: new Set([sourceEntity]),\n\t\t},\n\t];\n\n\twhile (queue.length > 0) {\n\t\tconst current = queue.shift();\n\t\tif (!current) continue;\n\n\t\tconst { entity, depth, path, visited } = current;\n\n\t\t// Don't go beyond max depth\n\t\tif (depth >= opts.maxDepth) continue;\n\n\t\tconst currentEntity = graph.entities.get(entity);\n\t\tif (!currentEntity) continue;\n\n\t\t// Explore has_many and has_one relationships\n\t\tfor (const [relName, rel] of currentEntity.relationships) {\n\t\t\t// Skip if already has a through defined\n\t\t\tif (rel.through) continue;\n\n\t\t\t// Only follow has_many and has_one relationships\n\t\t\tif (rel.type !== 'has_many' && rel.type !== 'has_one') continue;\n\n\t\t\tconst target = rel.target;\n\n\t\t\t// Skip excluded entities\n\t\t\tif (shouldExcludeEntity(target, opts)) continue;\n\n\t\t\t// Avoid cycles\n\t\t\tif (visited.has(target)) continue;\n\n\t\t\tconst newPath: PathHop[] = [\n\t\t\t\t...path,\n\t\t\t\t{\n\t\t\t\t\tvia: entity,\n\t\t\t\t\trelationship: relName,\n\t\t\t\t\tforeignKey: rel.foreignKey,\n\t\t\t\t},\n\t\t\t];\n\n\t\t\t// If we're at depth 2 or more, we have a valid transitive path\n\t\t\tif (depth >= 1) {\n\t\t\t\t// Check if a direct relationship already exists\n\t\t\t\tif (!hasDirectRelationship(sourceEntityData, target)) {\n\t\t\t\t\tconst transitivePath = buildTransitivePath(\n\t\t\t\t\t\tsourceEntity,\n\t\t\t\t\t\ttarget,\n\t\t\t\t\t\tnewPath\n\t\t\t\t\t);\n\t\t\t\t\tif (transitivePath) {\n\t\t\t\t\t\tpaths.push(transitivePath);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Continue searching deeper\n\t\t\tif (depth + 1 < opts.maxDepth) {\n\t\t\t\tqueue.push({\n\t\t\t\t\tentity: target,\n\t\t\t\t\tdepth: depth + 1,\n\t\t\t\t\tpath: newPath,\n\t\t\t\t\tvisited: new Set([...visited, target]),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn paths;\n}\n\n/**\n * Check if a direct relationship already exists between source and target\n */\nfunction hasDirectRelationship(\n\tsourceEntity: ParsedEntity,\n\ttargetName: string\n): boolean {\n\tfor (const rel of sourceEntity.relationships.values()) {\n\t\tif (rel.target === targetName && !rel.through) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Build a TransitivePath from BFS result\n */\nfunction buildTransitivePath(\n\tsource: string,\n\ttarget: string,\n\thops: PathHop[]\n): TransitivePath | null {\n\tif (hops.length === 0) return null;\n\n\t// Build through path: \"relationships.nested_relationship\"\n\tconst throughPath = hops.map((hop) => hop.relationship).join('.');\n\n\t// Generate semantic name\n\tconst suggestedName = generateSemanticName(source, target, hops);\n\n\t// Generate YAML snippet\n\tconst yamlSnippet = generateYamlSnippet(suggestedName, target, throughPath);\n\n\treturn {\n\t\tsource,\n\t\ttarget,\n\t\thops,\n\t\tsuggestedName,\n\t\tthroughPath,\n\t\tyamlSnippet,\n\t};\n}\n\n/**\n * Generate a semantic relationship name\n * Examples:\n * - user -> meetings -> action_items = \"meeting_action_items\"\n * - user -> owned_opportunities -> updates = \"owned_opportunity_updates\"\n */\nfunction generateSemanticName(\n\tsource: string,\n\ttarget: string,\n\thops: PathHop[]\n): string {\n\t// Use the first hop relationship name as a prefix\n\tconst firstHop = hops[0].relationship;\n\n\t// For simple 2-hop paths, combine first relationship with target\n\tif (hops.length === 2) {\n\t\t// Handle pluralization\n\t\tconst prefix = firstHop.replace(/s$/, ''); // singular form\n\t\treturn `${prefix}_${target}`;\n\t}\n\n\t// For 3-hop paths, combine all meaningful parts\n\tconst parts = [firstHop.replace(/s$/, ''), target];\n\treturn parts.join('_');\n}\n\n/**\n * Generate ready-to-paste YAML snippet\n */\nfunction generateYamlSnippet(\n\tname: string,\n\ttarget: string,\n\tthroughPath: string\n): string {\n\treturn ` ${name}:\n type: has_many\n target: ${target}\n through: \"${throughPath}\"`;\n}\n\n/**\n * Create a TransitiveSuggestion from a TransitivePath\n */\nfunction createSuggestion(path: TransitivePath): TransitiveSuggestion {\n\tconst pathDescription = [path.source, ...path.hops.map((h) => h.via), path.target]\n\t\t.join(' -> ');\n\n\treturn {\n\t\tseverity: 'info',\n\t\ttype: 'transitive_suggestion',\n\t\tentity: path.source,\n\t\tmessage: `Potential transitive relationship: ${pathDescription}`,\n\t\tsuggestion: `Add \"${path.suggestedName}\" relationship via \"${path.throughPath}\"`,\n\t\tpath,\n\t};\n}\n","/**\n * Manifest Persistence\n *\n * Handles reading, writing, and staleness detection for the codegen manifest.\n * Uses SHA-256 hash of entity files for deterministic staleness checking.\n */\n\nimport { createHash } from 'crypto';\nimport { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync, statSync } from 'fs';\nimport { join } from 'path';\nimport type {\n\tCodegenManifest,\n\tAnalysisResult,\n\tTransitiveSuggestion,\n\tManifestEntity,\n\tManifestField,\n\tManifestRelationship,\n\tManifestSuggestion,\n\tParsedEntity,\n} from './types';\nimport { findOrphanEntities, findCircularDependencies } from './graph-builder';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nexport const MANIFEST_FILE = 'manifest.json';\nexport const MANIFEST_VERSION = 1;\n\n/**\n * Get the manifest directory name (configurable via env var)\n */\nexport function getManifestDir(): string {\n\treturn process.env.CODEGEN_MANIFEST_DIR || '.codegen';\n}\n\n// ============================================================================\n// Path Utilities\n// ============================================================================\n\n/**\n * Get manifest directory and file paths\n */\nexport function getManifestPaths(projectRoot: string): { dir: string; file: string } {\n\tconst dir = join(projectRoot, getManifestDir());\n\tconst file = join(dir, MANIFEST_FILE);\n\treturn { dir, file };\n}\n\n// ============================================================================\n// Hash Computation\n// ============================================================================\n\n/**\n * Compute SHA-256 hash of all YAML files in the entities directory.\n * Results are deterministic (sorted file order).\n */\nexport async function computeEntityFilesHash(entitiesDir: string): Promise<string> {\n\tif (!existsSync(entitiesDir)) {\n\t\treturn createHash('sha256').update('').digest('hex');\n\t}\n\n\t// Recursively gather all YAML files\n\tconst yamlFiles: string[] = [];\n\n\tfunction walkDir(dir: string): void {\n\t\tconst entries = readdirSync(dir);\n\t\tfor (const entry of entries) {\n\t\t\tconst fullPath = join(dir, entry);\n\t\t\tconst stat = statSync(fullPath);\n\t\t\tif (stat.isDirectory()) {\n\t\t\t\twalkDir(fullPath);\n\t\t\t} else if (stat.isFile() && (entry.endsWith('.yaml') || entry.endsWith('.yml'))) {\n\t\t\t\tyamlFiles.push(fullPath);\n\t\t\t}\n\t\t}\n\t}\n\n\twalkDir(entitiesDir);\n\n\t// Sort for deterministic hashing\n\tyamlFiles.sort();\n\n\t// Compute combined hash\n\tconst hash = createHash('sha256');\n\tfor (const file of yamlFiles) {\n\t\tconst content = readFileSync(file, 'utf-8');\n\t\thash.update(file); // Include file path for uniqueness\n\t\thash.update(content);\n\t}\n\n\treturn hash.digest('hex');\n}\n\n// ============================================================================\n// Manifest I/O\n// ============================================================================\n\n/**\n * Read manifest from disk.\n * Returns null if not found or version mismatch.\n */\nexport function readManifest(projectRoot: string): CodegenManifest | null {\n\tconst { file } = getManifestPaths(projectRoot);\n\n\tif (!existsSync(file)) {\n\t\treturn null;\n\t}\n\n\ttry {\n\t\tconst content = readFileSync(file, 'utf-8');\n\t\tconst manifest = JSON.parse(content) as CodegenManifest;\n\n\t\t// Version check\n\t\tif (manifest.version !== MANIFEST_VERSION) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn manifest;\n\t} catch (error) {\n\t\t// Invalid JSON or read error\n\t\treturn null;\n\t}\n}\n\n/**\n * Write manifest to disk.\n * Creates .codegen directory if needed.\n */\nexport function writeManifest(projectRoot: string, manifest: CodegenManifest): void {\n\tconst { dir, file } = getManifestPaths(projectRoot);\n\n\t// Ensure directory exists\n\tif (!existsSync(dir)) {\n\t\tmkdirSync(dir, { recursive: true });\n\t}\n\n\t// Write manifest with pretty formatting\n\tconst content = JSON.stringify(manifest, null, 2);\n\twriteFileSync(file, content, 'utf-8');\n}\n\n// ============================================================================\n// Staleness Detection\n// ============================================================================\n\n/**\n * Check if manifest is stale (entity files have changed).\n */\nexport async function isManifestStale(\n\tprojectRoot: string,\n\tentitiesDir: string\n): Promise<boolean> {\n\tconst manifest = readManifest(projectRoot);\n\n\tif (!manifest) {\n\t\treturn true; // No manifest = stale\n\t}\n\n\tconst currentHash = await computeEntityFilesHash(entitiesDir);\n\treturn manifest.entityFilesHash !== currentHash;\n}\n\n// ============================================================================\n// Manifest Building\n// ============================================================================\n\n/**\n * Convert ParsedEntity to ManifestEntity\n */\nfunction toManifestEntity(entity: ParsedEntity): ManifestEntity {\n\tconst fields: Record<string, ManifestField> = {};\n\tfor (const [name, field] of entity.fields) {\n\t\tfields[name] = {\n\t\t\tname: field.name,\n\t\t\ttype: field.type,\n\t\t\trequired: field.required,\n\t\t\tnullable: field.nullable,\n\t\t\tunique: field.unique,\n\t\t\tindex: field.index,\n\t\t\tforeignKey: field.foreignKey,\n\t\t\tchoices: field.choices,\n\t\t};\n\t}\n\n\tconst relationships: Record<string, ManifestRelationship> = {};\n\tfor (const [name, rel] of entity.relationships) {\n\t\trelationships[name] = {\n\t\t\ttype: rel.type,\n\t\t\ttarget: rel.target,\n\t\t\tforeignKey: rel.foreignKey,\n\t\t\tthrough: rel.through,\n\t\t\tinverse: rel.inverse,\n\t\t};\n\t}\n\n\treturn {\n\t\tsourcePath: entity.sourcePath,\n\t\ttable: entity.table,\n\t\tplural: entity.plural,\n\t\tfields,\n\t\trelationships,\n\t\tbehaviors: entity.behaviors,\n\t};\n}\n\n/**\n * Merge transitive suggestions with existing manifest suggestions.\n * Preserves status (pending/accepted/skipped) from existing manifest.\n */\nfunction mergeSuggestions(\n\tnewSuggestions: TransitiveSuggestion[],\n\texistingManifest?: CodegenManifest | null\n): ManifestSuggestion[] {\n\tconst now = new Date().toISOString();\n\tconst existingSuggestions = existingManifest?.suggestions.transitive || [];\n\tconst existingMap = new Map<string, ManifestSuggestion>();\n\n\t// Build map of existing suggestions by ID\n\tfor (const existing of existingSuggestions) {\n\t\texistingMap.set(existing.id, existing);\n\t}\n\n\t// Merge new suggestions\n\tconst merged: ManifestSuggestion[] = [];\n\n\tfor (const suggestion of newSuggestions) {\n\t\tconst id = `${suggestion.path.source}->${suggestion.path.target}`;\n\t\tconst existing = existingMap.get(id);\n\n\t\tif (existing) {\n\t\t\t// Preserve existing suggestion with updated content\n\t\t\tmerged.push({\n\t\t\t\tid,\n\t\t\t\tsource: suggestion.path.source,\n\t\t\t\ttarget: suggestion.path.target,\n\t\t\t\tthroughPath: suggestion.path.throughPath,\n\t\t\t\tsuggestedName: suggestion.path.suggestedName,\n\t\t\t\tyamlSnippet: suggestion.path.yamlSnippet,\n\t\t\t\tstatus: existing.status, // Preserve status\n\t\t\t\tdetectedAt: existing.detectedAt, // Preserve original detection time\n\t\t\t\tresolvedAt: existing.resolvedAt,\n\t\t\t});\n\t\t\texistingMap.delete(id); // Mark as processed\n\t\t} else {\n\t\t\t// New suggestion\n\t\t\tmerged.push({\n\t\t\t\tid,\n\t\t\t\tsource: suggestion.path.source,\n\t\t\t\ttarget: suggestion.path.target,\n\t\t\t\tthroughPath: suggestion.path.throughPath,\n\t\t\t\tsuggestedName: suggestion.path.suggestedName,\n\t\t\t\tyamlSnippet: suggestion.path.yamlSnippet,\n\t\t\t\tstatus: 'pending',\n\t\t\t\tdetectedAt: now,\n\t\t\t});\n\t\t}\n\t}\n\n\t// Keep resolved suggestions from existing manifest (accepted/skipped)\n\tfor (const [id, existing] of existingMap) {\n\t\tif (existing.status !== 'pending') {\n\t\t\tmerged.push(existing);\n\t\t}\n\t\t// Pending suggestions that are no longer detected are dropped\n\t}\n\n\treturn merged;\n}\n\n/**\n * Build manifest from analysis result\n */\nexport async function buildManifest(\n\tanalysis: AnalysisResult,\n\ttransitiveSuggestions: TransitiveSuggestion[],\n\tentitiesDir: string,\n\texistingManifest?: CodegenManifest | null\n): Promise<CodegenManifest> {\n\tconst entities: Record<string, ManifestEntity> = {};\n\n\t// Convert entities\n\tfor (const entity of analysis.entities) {\n\t\tentities[entity.name] = toManifestEntity(entity);\n\t}\n\n\t// Build graph metadata\n\tconst orphans = findOrphanEntities(analysis.graph);\n\tconst cycles = findCircularDependencies(analysis.graph);\n\n\t// Merge suggestions (preserving existing status)\n\tconst mergedSuggestions = mergeSuggestions(transitiveSuggestions, existingManifest);\n\n\t// Compute entity files hash\n\tconst entityFilesHash = await computeEntityFilesHash(entitiesDir);\n\n\tconst manifest: CodegenManifest = {\n\t\tversion: MANIFEST_VERSION,\n\t\tgeneratedAt: new Date().toISOString(),\n\t\tentityFilesHash,\n\t\tentities,\n\t\tgraph: {\n\t\t\tedges: analysis.graph.edges.map((edge) => ({\n\t\t\t\tfrom: edge.from,\n\t\t\t\tto: edge.to,\n\t\t\t\trelationship: edge.relationship.name,\n\t\t\t\tcardinality: edge.cardinality === 'N:M' ? '1:N' : edge.cardinality,\n\t\t\t\tbidirectional: edge.bidirectional,\n\t\t\t})),\n\t\t\torphans,\n\t\t\tcycles,\n\t\t},\n\t\tsuggestions: {\n\t\t\ttransitive: mergedSuggestions,\n\t\t},\n\t\tstatistics: {\n\t\t\ttotalEntities: analysis.statistics.totalEntities,\n\t\t\ttotalFields: analysis.statistics.totalFields,\n\t\t\ttotalRelationships: analysis.statistics.totalRelationships,\n\t\t\ttransitivePathsDetected: transitiveSuggestions.length,\n\t\t},\n\t};\n\n\treturn manifest;\n}\n\n// ============================================================================\n// Suggestion Management\n// ============================================================================\n\n/**\n * Update status of a specific suggestion.\n * Returns true if updated, false if suggestion not found.\n */\nexport function updateSuggestionStatus(\n\tprojectRoot: string,\n\tsuggestionId: string,\n\tstatus: 'accepted' | 'skipped'\n): boolean {\n\tconst manifest = readManifest(projectRoot);\n\tif (!manifest) {\n\t\treturn false;\n\t}\n\n\tconst suggestion = manifest.suggestions.transitive.find((s) => s.id === suggestionId);\n\tif (!suggestion) {\n\t\treturn false;\n\t}\n\n\tsuggestion.status = status;\n\tsuggestion.resolvedAt = new Date().toISOString();\n\n\twriteManifest(projectRoot, manifest);\n\treturn true;\n}\n\n/**\n * Update status of all pending suggestions.\n * Returns count of updated suggestions.\n */\nexport function updateAllSuggestionStatus(\n\tprojectRoot: string,\n\tstatus: 'accepted' | 'skipped'\n): number {\n\tconst manifest = readManifest(projectRoot);\n\tif (!manifest) {\n\t\treturn 0;\n\t}\n\n\tlet count = 0;\n\tconst now = new Date().toISOString();\n\n\tfor (const suggestion of manifest.suggestions.transitive) {\n\t\tif (suggestion.status === 'pending') {\n\t\t\tsuggestion.status = status;\n\t\t\tsuggestion.resolvedAt = now;\n\t\t\tcount++;\n\t\t}\n\t}\n\n\tif (count > 0) {\n\t\twriteManifest(projectRoot, manifest);\n\t}\n\n\treturn count;\n}\n\n/**\n * Get all pending suggestions from manifest.\n */\nexport function getPendingSuggestions(projectRoot: string): ManifestSuggestion[] {\n\tconst manifest = readManifest(projectRoot);\n\tif (!manifest) {\n\t\treturn [];\n\t}\n\n\treturn manifest.suggestions.transitive.filter((s) => s.status === 'pending');\n}\n","/**\n * Serializes a DomainGraph to plain JSON (converts Maps to Records).\n *\n * Used by the CLI `codegen project graph` command to produce JSON\n * that the schema-graph-viewer can consume via its SchemaAdapter.\n */\nimport type {\n DomainGraph,\n ParsedEntity,\n ParsedField,\n ParsedRelationship,\n ParsedRelationshipDefinition,\n} from './types';\n\nexport interface SerializedDomainGraph {\n entities: Record<string, SerializedEntity>;\n relationshipDefinitions: Record<string, SerializedRelationshipDefinition>;\n edges: SerializedEdge[];\n}\n\nexport interface SerializedEntity {\n name: string;\n plural: string;\n table: string;\n pattern?: string;\n patterns?: string[];\n patternConfig?: Record<string, unknown>;\n fields: Record<string, SerializedField>;\n relationships: Record<string, SerializedRelationship>;\n behaviors: string[];\n queries?: Array<{ by: string[]; unique?: boolean; order?: string }>;\n sourcePath: string;\n}\n\nexport interface SerializedField {\n name: string;\n type: string;\n required: boolean;\n nullable: boolean;\n unique: boolean;\n index: boolean;\n foreignKey?: { table: string; column: string };\n choices?: string[];\n}\n\nexport interface SerializedRelationship {\n name: string;\n type: 'belongs_to' | 'has_many' | 'has_one';\n target: string;\n foreignKey: string;\n inverse?: string;\n through?: string;\n resolved: boolean;\n}\n\nexport interface SerializedRelationshipDefinition {\n name: string;\n table: string;\n from: string;\n to: string;\n selfReferential: boolean;\n fromColumn: string;\n toColumn: string;\n types: Array<{ name: string; inverse?: string; bidirectional: boolean; directed: boolean }>;\n hasTypes: boolean;\n temporal: boolean;\n sourced: boolean;\n onDeleteFrom: string;\n onDeleteTo: string;\n uniqueOn: string[];\n fields: Record<string, SerializedField>;\n queries?: Array<{ by: string[]; unique?: boolean; order?: string }>;\n sourcePath: string;\n}\n\nexport interface SerializedEdge {\n from: string;\n to: string;\n relationship: SerializedRelationship;\n cardinality: '1:1' | '1:N' | 'N:1' | 'N:M';\n bidirectional: boolean;\n}\n\nfunction serializeFields(fields: Map<string, ParsedField>): Record<string, SerializedField> {\n const result: Record<string, SerializedField> = {};\n for (const [key, f] of fields) {\n result[key] = {\n name: f.name,\n type: f.type,\n required: f.required,\n nullable: f.nullable,\n unique: f.unique,\n index: f.index,\n foreignKey: f.foreignKey,\n choices: f.choices,\n };\n }\n return result;\n}\n\nfunction serializeRelationships(\n rels: Map<string, ParsedRelationship>,\n): Record<string, SerializedRelationship> {\n const result: Record<string, SerializedRelationship> = {};\n for (const [key, r] of rels) {\n result[key] = {\n name: r.name,\n type: r.type,\n target: r.target,\n foreignKey: r.foreignKey,\n inverse: r.inverse,\n through: r.through,\n resolved: r.resolved,\n };\n }\n return result;\n}\n\n/**\n * Convert a DomainGraph (with Maps) to a plain JSON-serializable object.\n */\nexport function serializeDomainGraph(graph: DomainGraph): SerializedDomainGraph {\n const entities: Record<string, SerializedEntity> = {};\n for (const [key, entity] of graph.entities) {\n entities[key] = {\n name: entity.name,\n plural: entity.plural,\n table: entity.table,\n pattern: entity.pattern,\n patterns: entity.patterns,\n patternConfig: entity.patternConfig,\n fields: serializeFields(entity.fields),\n relationships: serializeRelationships(entity.relationships),\n behaviors: entity.behaviors,\n queries: entity.queries?.map((q) => ({\n by: q.by,\n unique: q.unique,\n order: q.order,\n })),\n sourcePath: entity.sourcePath,\n };\n }\n\n const relationshipDefinitions: Record<string, SerializedRelationshipDefinition> = {};\n for (const [key, relDef] of graph.relationshipDefinitions) {\n relationshipDefinitions[key] = {\n name: relDef.name,\n table: relDef.table,\n from: relDef.from,\n to: relDef.to,\n selfReferential: relDef.selfReferential,\n fromColumn: relDef.fromColumn,\n toColumn: relDef.toColumn,\n types: relDef.types,\n hasTypes: relDef.hasTypes,\n temporal: relDef.temporal,\n sourced: relDef.sourced,\n onDeleteFrom: relDef.onDeleteFrom,\n onDeleteTo: relDef.onDeleteTo,\n uniqueOn: relDef.uniqueOn,\n fields: serializeFields(relDef.fields),\n queries: relDef.queries?.map((q) => ({\n by: q.by,\n unique: q.unique,\n order: q.order,\n })),\n sourcePath: relDef.sourcePath,\n };\n }\n\n return {\n entities,\n relationshipDefinitions,\n edges: graph.edges.map((e) => ({\n from: e.from,\n to: e.to,\n relationship: {\n name: e.relationship.name,\n type: e.relationship.type,\n target: e.relationship.target,\n foreignKey: e.relationship.foreignKey,\n inverse: e.relationship.inverse,\n through: e.relationship.through,\n resolved: e.relationship.resolved,\n },\n cardinality: e.cardinality,\n bidirectional: e.bidirectional,\n })),\n };\n}\n","/**\n * Pattern Registry — library + app pattern storage and discovery.\n *\n * Three stores keyed by pattern name:\n * - `LIBRARY_PATTERNS` — seeded by the codegen package itself when the\n * `src/patterns/library/*` barrel imports execute. Consumers never\n * list these in `codegen.config.yaml patterns:`. Domain only.\n * - `APP_PATTERNS` — populated by `loadAppPatterns()` from a\n * consumer-supplied glob set (default `src/patterns/*.pattern.ts`).\n * Domain only.\n * - `ORCHESTRATION_APP_PATTERNS` — populated by the same loader,\n * routed by `kind: 'orchestration'` (ADR-032). No library\n * orchestration patterns ship in Phase 3-1.\n *\n * `getPattern()` checks app patterns first so a consumer could, in\n * principle, shadow a library pattern by using the same `name`. That's\n * not a documented feature, but nothing in the API prevents it.\n *\n * The Hygen subprocess (`src/cli/shared/hygen.ts:64`) reloads this module\n * independently — it has no shared memory with the CLI process. Both\n * loads are deterministic, side-effect-free reads of the same files, so\n * the registry contents are identical across processes. The registry\n * test suite asserts this determinism explicitly.\n *\n * See `docs/adrs/ADR-031-app-defined-patterns.md` §\"Decision 5\" and\n * `docs/specs/app-defined-patterns-implementation.md` §3.\n */\n\nimport { glob } from 'glob';\nimport path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport {\n\tisOrchestrationPattern,\n\tisPatternDefinition,\n\ttype AnyPatternDefinition,\n\ttype OrchestrationPatternDefinition,\n\ttype PatternDefinition,\n} from './pattern-definition.js';\n\n// ============================================================================\n// Stores\n// ============================================================================\n\nconst LIBRARY_PATTERNS: Map<string, PatternDefinition> = new Map();\nconst APP_PATTERNS: Map<string, PatternDefinition> = new Map();\n\n/**\n * Orchestration patterns (ADR-032). Library never ships orchestration\n * patterns in Phase 3-1 — only the app-pattern map exists for this kind.\n * If a library-shipped orchestration pattern ever lands, add a parallel\n * `LIBRARY_ORCHESTRATION_PATTERNS` map; for now keep storage minimal.\n */\nconst ORCHESTRATION_APP_PATTERNS: Map<string, OrchestrationPatternDefinition> =\n\tnew Map();\n\n/**\n * Every pattern must contribute *something* — either at least one column\n * or at least one of the two class references. A pattern that contributes\n * nothing would generate no useful output and almost certainly indicates\n * a typo or an unfinished definition.\n */\nfunction assertHasContribution(def: PatternDefinition): void {\n\tconst hasColumns = Array.isArray(def.columns) && def.columns.length > 0;\n\tconst hasRepo =\n\t\ttypeof def.repositoryClass === 'string' && def.repositoryClass.length > 0;\n\tconst hasService =\n\t\ttypeof def.serviceClass === 'string' && def.serviceClass.length > 0;\n\n\tif (!hasColumns && !hasRepo && !hasService) {\n\t\tthrow new Error(\n\t\t\t`Pattern '${def.name}' contributes nothing — at least one of ` +\n\t\t\t\t'`columns`, `repositoryClass`, or `serviceClass` is required.',\n\t\t);\n\t}\n}\n\n/**\n * Orchestration counterpart to `assertHasContribution`. An orchestration\n * pattern's minimum contribution is one registry with at least one entry —\n * a registry with zero entries would emit a token + module that nothing\n * resolves to, almost certainly a typo. Detailed entry validation\n * (duplicate keys, malformed entries, co-keyed mismatches) lives in the\n * project-level validator so loader behaviour stays symmetrical with the\n * domain side: load is non-throwing for content-level issues, validator\n * is the single authoritative reporter.\n */\nfunction assertOrchestrationContribution(\n\tdef: OrchestrationPatternDefinition,\n): void {\n\tif (!def.registry || typeof def.registry !== 'object') {\n\t\tthrow new Error(\n\t\t\t`Orchestration pattern '${def.name}' is missing a 'registry' field.`,\n\t\t);\n\t}\n\tif (\n\t\ttypeof def.registry.keyType !== 'string' ||\n\t\tdef.registry.keyType.length === 0\n\t) {\n\t\tthrow new Error(\n\t\t\t`Orchestration pattern '${def.name}' registry.keyType must be a non-empty string.`,\n\t\t);\n\t}\n\tif (\n\t\ttypeof def.registry.valueType !== 'string' ||\n\t\tdef.registry.valueType.length === 0\n\t) {\n\t\tthrow new Error(\n\t\t\t`Orchestration pattern '${def.name}' registry.valueType must be a non-empty string.`,\n\t\t);\n\t}\n\tif (\n\t\t!Array.isArray(def.registry.entries) ||\n\t\tdef.registry.entries.length === 0\n\t) {\n\t\tthrow new Error(\n\t\t\t`Orchestration pattern '${def.name}' registry.entries must contain at least one entry.`,\n\t\t);\n\t}\n}\n\n// ============================================================================\n// Library pattern registration\n// ============================================================================\n\n/**\n * Insert a library pattern into the registry. Called once by each\n * `src/patterns/library/*.pattern.ts` file via the barrel. Re-registering\n * the same name overwrites the previous value silently; this is\n * intentional for hot-reload scenarios but should not happen in normal\n * use.\n */\nexport function registerLibraryPattern(def: PatternDefinition): void {\n\tassertHasContribution(def);\n\tLIBRARY_PATTERNS.set(def.name, def);\n}\n\n// ============================================================================\n// Lookup\n// ============================================================================\n\n/**\n * Resolve a **domain** pattern by name. App patterns shadow library\n * patterns with the same name — useful in principle but not a documented\n * feature.\n *\n * Orchestration patterns live in a disjoint store; use\n * `getOrchestrationPattern()` to look those up. The two surfaces are\n * intentionally separate (ADR-032 Decision 8) so callers don't have to\n * narrow the result on every callsite.\n */\nexport function getPattern(name: string): PatternDefinition | undefined {\n\treturn APP_PATTERNS.get(name) ?? LIBRARY_PATTERNS.get(name);\n}\n\n/**\n * Return every registered domain pattern name (library + app), sorted for\n * deterministic output. The two-process determinism test relies on this\n * ordering being stable across processes. Orchestration names are NOT\n * included — see `getOrchestrationPatternNames()`.\n */\nexport function getAllPatternNames(): string[] {\n\tconst set = new Set<string>([\n\t\t...LIBRARY_PATTERNS.keys(),\n\t\t...APP_PATTERNS.keys(),\n\t]);\n\treturn [...set].sort();\n}\n\n/** Library-only view — mainly for debugging and tests. */\nexport function getLibraryPatternNames(): string[] {\n\treturn [...LIBRARY_PATTERNS.keys()].sort();\n}\n\n/** App-only view — mainly for debugging and tests. */\nexport function getAppPatternNames(): string[] {\n\treturn [...APP_PATTERNS.keys()].sort();\n}\n\n// ============================================================================\n// Orchestration accessors (ADR-032)\n// ============================================================================\n\n/** Resolve an orchestration pattern by name. */\nexport function getOrchestrationPattern(\n\tname: string,\n): OrchestrationPatternDefinition | undefined {\n\treturn ORCHESTRATION_APP_PATTERNS.get(name);\n}\n\n/** Sorted list of orchestration pattern names. */\nexport function getOrchestrationPatternNames(): string[] {\n\treturn [...ORCHESTRATION_APP_PATTERNS.keys()].sort();\n}\n\n/**\n * Every registered orchestration pattern, sorted by name. The\n * project-level validator iterates this list in one place so issue\n * ordering is stable across processes.\n */\nexport function getAllOrchestrationPatterns(): OrchestrationPatternDefinition[] {\n\treturn getOrchestrationPatternNames().map(\n\t\t(n) => ORCHESTRATION_APP_PATTERNS.get(n)!,\n\t);\n}\n\n// ============================================================================\n// App pattern discovery\n// ============================================================================\n\nexport interface LoadAppPatternsResult {\n\t/** Pattern names that were successfully registered, sorted */\n\tloaded: string[];\n\t/** One human-readable error per failed file import */\n\terrors: string[];\n}\n\n/**\n * Expand every glob in `manifestPaths` relative to `cwd`, dynamic-import\n * each matching file, and register every exported value that passes\n * `isPatternDefinition()`. Exports whose name ends in `Pattern` and\n * pass the shape check are registered; other exports are ignored so\n * that files can export helper values alongside their pattern.\n *\n * Import failures are non-fatal — the error is collected and returned\n * so the CLI can surface it without breaking generation of unrelated\n * entities. A pattern that fails the \"at-least-one-contribution\" check\n * surfaces here as an error too.\n *\n * Idempotent: calling twice with the same arguments leaves `APP_PATTERNS`\n * in the same state as calling once.\n */\nexport async function loadAppPatterns(\n\tmanifestPaths: string[],\n\tcwd: string,\n): Promise<LoadAppPatternsResult> {\n\tconst loaded = new Set<string>();\n\tconst errors: string[] = [];\n\n\t// Collect + dedupe absolute file paths across every glob pattern so\n\t// a file matched by two globs is imported once.\n\tconst files = new Set<string>();\n\tfor (const raw of manifestPaths) {\n\t\ttry {\n\t\t\tconst expanded = await glob(raw, { cwd, absolute: true, nodir: true });\n\t\t\tfor (const filePath of expanded) {\n\t\t\t\tfiles.add(filePath);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\terrors.push(\n\t\t\t\t`Failed to expand pattern glob '${raw}': ${stringifyError(err)}`,\n\t\t\t);\n\t\t}\n\t}\n\n\t// Sort so dynamic-import order is deterministic across processes —\n\t// the Hygen subprocess relies on this to produce the same registry\n\t// as the CLI.\n\tconst sortedFiles = [...files].sort();\n\n\tfor (const filePath of sortedFiles) {\n\t\ttry {\n\t\t\t// `pathToFileURL` is required for absolute-path dynamic imports on\n\t\t\t// Windows and makes the behavior identical on macOS/Linux.\n\t\t\tconst mod = (await import(pathToFileURL(filePath).href)) as Record<\n\t\t\t\tstring,\n\t\t\t\tunknown\n\t\t\t>;\n\t\t\tfor (const [key, val] of Object.entries(mod)) {\n\t\t\t\tif (!key.endsWith('Pattern')) continue;\n\t\t\t\tif (!isPatternDefinition(val)) continue;\n\n\t\t\t\t// Route on `kind`. Domain (default) and orchestration land in\n\t\t\t\t// disjoint maps; same-name collisions within either map are\n\t\t\t\t// load-time errors (silent overwrite was wrong by CLAUDE.md\n\t\t\t\t// \"architectural correctness\" — see ADR-032 §Composition rules\n\t\t\t\t// row 1).\n\t\t\t\tif (isOrchestrationPattern(val as unknown as AnyPatternDefinition)) {\n\t\t\t\t\tconst orch = val as unknown as OrchestrationPatternDefinition;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tassertOrchestrationContribution(orch);\n\t\t\t\t\t} catch (assertErr) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t`Orchestration pattern '${orch.name}' in ${relPath(filePath, cwd)} is invalid: ${stringifyError(assertErr)}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tconst existingOrch = ORCHESTRATION_APP_PATTERNS.get(orch.name);\n\t\t\t\t\tif (existingOrch && existingOrch !== orch) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t`Orchestration pattern '${orch.name}' in ${relPath(filePath, cwd)} duplicates a previously loaded orchestration pattern. Pattern names must be unique.`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tORCHESTRATION_APP_PATTERNS.set(orch.name, orch);\n\t\t\t\t\tloaded.add(orch.name);\n\t\t\t\t} else {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tassertHasContribution(val);\n\t\t\t\t\t} catch (assertErr) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t`Pattern '${val.name}' in ${relPath(filePath, cwd)} is invalid: ${stringifyError(assertErr)}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tconst existingDom = APP_PATTERNS.get(val.name);\n\t\t\t\t\tif (existingDom && existingDom !== val) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t`Pattern '${val.name}' in ${relPath(filePath, cwd)} duplicates a previously loaded app pattern. Pattern names must be unique.`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tAPP_PATTERNS.set(val.name, val);\n\t\t\t\t\tloaded.add(val.name);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (err) {\n\t\t\terrors.push(\n\t\t\t\t`Failed to load pattern file '${relPath(filePath, cwd)}': ${stringifyError(err)}`,\n\t\t\t);\n\t\t}\n\t}\n\n\treturn {\n\t\tloaded: [...loaded].sort(),\n\t\terrors,\n\t};\n}\n\n// ============================================================================\n// Test-only reset\n// ============================================================================\n\n/**\n * Clear every registered app pattern and, optionally, library patterns too.\n *\n * Intended for unit tests that build isolated scenarios on top of a clean\n * registry. Not exported from the barrel — tests import it directly from\n * `./registry.js`.\n */\nexport function _resetRegistryForTests(\n\topts: { includeLibrary?: boolean } = {},\n): void {\n\tAPP_PATTERNS.clear();\n\tORCHESTRATION_APP_PATTERNS.clear();\n\tif (opts.includeLibrary) {\n\t\tLIBRARY_PATTERNS.clear();\n\t}\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction stringifyError(err: unknown): string {\n\tif (err instanceof Error) return err.message;\n\treturn String(err);\n}\n\nfunction relPath(abs: string, cwd: string): string {\n\ttry {\n\t\treturn path.relative(cwd, abs) || abs;\n\t} catch {\n\t\treturn abs;\n\t}\n}\n","/**\n * Pattern Definition — pure metadata record returned by an identity function.\n *\n * `definePattern()` is the registration artifact for both library-shipped and\n * app-defined patterns. It carries only names + import paths for the classes\n * a generated entity should extend — never the class constructors themselves.\n * This keeps the codegen pipeline free of TS class-evaluation cost and avoids\n * `reflect-metadata`, which lets the Hygen subprocess cheaply rebuild the\n * registry (see `src/cli/shared/hygen.ts` — the registry loads twice per\n * `entity new` invocation).\n *\n * Two pattern kinds share this surface:\n * - **domain** (default; ADR-031) — `PatternDefinition`. Contributes\n * repository/service base classes, columns, behaviors to entities that\n * declare `pattern:`/`patterns:` in YAML.\n * - **orchestration** (ADR-032) — `OrchestrationPatternDefinition`. Declares\n * a DI registry + optional dispatcher scaffold. Not entity-attached;\n * codegen emits a NestJS module under `src/orchestration/` instead.\n *\n * See `docs/adrs/ADR-031-app-defined-patterns.md` §\"Decision 1\" for the\n * domain binding surface and `docs/adrs/ADR-032-orchestration-patterns.md`\n * for the orchestration kind.\n */\n\nimport type { ZodSchema } from 'zod';\n\n/**\n * A column a pattern contributes to every entity that declares it.\n *\n * Column-level conflicts between patterns, between a pattern and an\n * entity-declared field, or between a pattern and a behavior-contributed\n * field are codegen-time hard errors; see\n * `src/patterns/validate-composition.ts`.\n */\nexport interface PatternColumnContribution {\n\t/** snake_case column name — matches the database column */\n\tname: string;\n\t/** Drizzle column type string, e.g. \"varchar(255)\" or \"text\" */\n\ttype: string;\n}\n\n/**\n * Discriminator for the two pattern shapes. Default is `\"domain\"` to preserve\n * Phase 1 (ADR-031) behaviour — every existing PatternDefinition without a\n * `kind` field continues to register as a domain pattern.\n */\nexport type PatternKind = 'domain' | 'orchestration';\n\n/**\n * The full pattern metadata record. Every `definePattern({...})` call\n * returns a value of this shape; the library and consumer registries\n * store these and look them up by `name`.\n */\nexport interface PatternDefinition<TConfig = unknown> {\n\t/** Unique name used in YAML — e.g. `pattern: Integrated` */\n\tname: string;\n\n\t/**\n\t * ADR-032: defaults to `\"domain\"`. Phase 3 adds `\"orchestration\"` as a\n\t * disjoint shape (see `OrchestrationPatternDefinition`). Domain\n\t * `PatternDefinition` instances must omit this field or set it to\n\t * `\"domain\"`; the loader routes orchestration values to a separate map.\n\t */\n\tkind?: 'domain';\n\n\t/**\n\t * Built-in patterns this extends, by name. Phase 1 supports single-depth\n\t * chains only — a pattern may `extends: ['Integrated']` but the transitive\n\t * chain is not yet resolved. Multi-depth inheritance is deferred until\n\t * a real consumer asks.\n\t */\n\textends?: string[];\n\n\t/** Constructor name codegen emits in the generated repo's `extends` clause */\n\trepositoryClass?: string;\n\t/** Constructor name codegen emits in the generated service's `extends` clause */\n\tserviceClass?: string;\n\n\t/**\n\t * Fully-qualified TypeScript path alias the consumer's tsconfig resolves.\n\t * Library patterns use the consumer-installed runtime base class path\n\t * (e.g. `@shared/base-classes/integrated-entity-repository`); app patterns\n\t * use whatever alias the consumer has configured (e.g. `@/patterns/...`).\n\t */\n\trepositoryImport?: string;\n\t/** Same as `repositoryImport` but for the service base class */\n\tserviceImport?: string;\n\n\t/**\n\t * Documentation-only method-signature strings emitted as comments in the\n\t * generated repo. Exist purely so app authors reading the generated file\n\t * see what their concrete class inherits without jumping to the base.\n\t */\n\trepositoryInheritedMethods?: string[];\n\t/** Same as `repositoryInheritedMethods` but for the service base class */\n\tserviceInheritedMethods?: string[];\n\n\t/**\n\t * Columns this pattern adds to every entity that declares it. Used by\n\t * the composition validator to detect column-name collisions.\n\t */\n\tcolumns?: PatternColumnContribution[];\n\n\t/**\n\t * Behaviors this pattern implicitly enables. Entity YAML need not\n\t * re-declare them; duplicates across patterns are silent-deduped.\n\t */\n\timpliedBehaviors?: string[];\n\n\t/**\n\t * Zod schema that validates the per-entity `config:` block for this\n\t * pattern at parse time. When absent, entities may not supply a `config:`\n\t * entry for this pattern and codegen emits no `patternConfig` property.\n\t */\n\tconfigSchema?: ZodSchema<TConfig>;\n\n\t/** One-line description for codegen help output and error messages */\n\tdescription?: string;\n}\n\n/**\n * Identity function that returns its argument unchanged. The body is trivial\n * on purpose — the whole point is to give TypeScript a hook for generic\n * inference on `TConfig` while leaving the runtime value a plain object\n * registered by the codegen loader.\n */\nexport function definePattern<TConfig = unknown>(\n\tdef: PatternDefinition<TConfig>,\n): PatternDefinition<TConfig> {\n\treturn def;\n}\n\n/**\n * Shape check for values produced by `import()`ing an app pattern file.\n * The registry loader runs this on every exported value it finds; only\n * values that pass are registered.\n *\n * We keep this deliberately loose — a `name` string is the whole\n * requirement — because a pattern that contributes neither columns nor\n * class references is still a *valid* identity pattern (e.g. `BasePattern`\n * exists to anchor the `extends` chain without contributing anything).\n * Stricter shape rules belong in the registry's \"at-least-one-contribution\"\n * check, not here.\n *\n * This function is intentionally **kind-agnostic** — both\n * `PatternDefinition` (domain) and `OrchestrationPatternDefinition`\n * (orchestration) pass. The discriminator routing happens in the loader\n * via `isOrchestrationPattern()`/`isDomainPattern()`.\n */\nexport function isPatternDefinition(val: unknown): val is PatternDefinition {\n\treturn (\n\t\ttypeof val === 'object' &&\n\t\tval !== null &&\n\t\t'name' in val &&\n\t\ttypeof (val as { name: unknown }).name === 'string'\n\t);\n}\n\n// ============================================================================\n// Orchestration kind (ADR-032)\n// ============================================================================\n\n/**\n * One registry's declarative shape. ADR-032 §\"The Proposal\".\n *\n * Phase 3-1 records this; Phase 3-2 codegen reads it to emit token files,\n * provider blocks, and dispatcher overload signatures. Phase 3-1 validates\n * only what is statically checkable from this record alone — see\n * `validate-orchestration.ts` for the rules and their deferral notes.\n */\nexport interface OrchestrationRegistrySpec {\n\t/**\n\t * Identifier for co-keyed sibling registries (ADR-032 Phase 3-2/3, O-1).\n\t *\n\t * The PRIMARY registry never carries a `name` — its tokens / methods are\n\t * derived from the pattern name alone (`${PATTERN_CONST}_REGISTRY`,\n\t * `select(...)`). Each co-keyed sibling MUST carry an explicit `name`\n\t * which the emitter uppercases for the token suffix and PascalCases for\n\t * the dispatcher method suffix:\n\t *\n\t * `coKeyedRegistries: [{ name: 'auth', valueType: 'IAuthStrategy' ... }]`\n\t * ⇒ `CRM_PORTS_AUTH_REGISTRY` token + `selectAuth(...)` method.\n\t *\n\t * No auto-stripping of \"I\" prefix or \"Strategy/Port/Adapter/Provider\"\n\t * suffixes — authors pick what reads right.\n\t */\n\tname?: string;\n\t/**\n\t * Type alias the consumer's tsconfig resolves (e.g. `\"CrmAdapterDomain\"`).\n\t * Phase 3-1 stores this string verbatim. Resolution that the path actually\n\t * imports a concrete TS enum is deferred to Phase 3-2 emission, where\n\t * codegen will need to read the consumer's source tree.\n\t */\n\tkeyType: string;\n\t/**\n\t * Module specifier the emitter writes into `import type { keyType } from\n\t * '<keyTypeImport>'`. Required at Phase 3-2 emission; the generator emits\n\t * `pattern_missing_import_path` if absent. (ADR-032 Phase 3-2 §3.4 / O-3.)\n\t */\n\tkeyTypeImport?: string;\n\t/** Same shape as `keyType` — the registry's value-type interface ref. */\n\tvalueType: string;\n\t/** Module specifier for `valueType` import. See `keyTypeImport`. */\n\tvalueTypeImport?: string;\n\tentries: ReadonlyArray<{\n\t\t/** Stable string key — must be unique within this registry. */\n\t\tkey: string;\n\t\t/**\n\t\t * Concrete provider class name (NOT a DI token string). Codegen will\n\t\t * import this and use it as the constructor injectable.\n\t\t * Phase 3-1 records it; Phase 3-2 verifies it resolves.\n\t\t */\n\t\tprovider: string;\n\t\t/** Module specifier for `provider` import. See `keyTypeImport`. */\n\t\tproviderImport?: string;\n\t}>;\n}\n\n/**\n * Orchestration pattern — declarative DI registry + optional dispatcher\n * scaffold. ADR-032 §\"The Proposal\" + Decisions 1-8.\n *\n * Disjoint from `PatternDefinition` (domain): no columns, no\n * repository/service base class, no entity-level patternConfig. Composition\n * with domain patterns happens only at the DI layer in the consumer's\n * generated code, not in entity YAML.\n */\nexport interface OrchestrationPatternDefinition {\n\tname: string;\n\tkind: 'orchestration';\n\t/** Primary registry (always present). */\n\tregistry: OrchestrationRegistrySpec;\n\t/**\n\t * Sibling registries that share the primary registry's key space.\n\t * ADR-032 Decision 2 — co-keyed groups are a first-class field.\n\t * Validator enforces matching `keyType` across the group.\n\t */\n\tcoKeyedRegistries?: ReadonlyArray<OrchestrationRegistrySpec>;\n\t/** Optional dispatcher scaffold spec (ADR-032 Decision 4 + 5). */\n\tdispatcher?: {\n\t\t/** Class name to emit (e.g. `\"CrmPortsDispatcher\"`). */\n\t\tclassName: string;\n\t\t/**\n\t\t * Method name the consumer overrides in their subclass to fill the\n\t\t * assembly body (ADR-032 Decision 5).\n\t\t */\n\t\tassemblySlot: string;\n\t};\n\t/** One-line description for help output and error messages. */\n\tdescription?: string;\n}\n\n/** Union for callers that need to handle both shapes. */\nexport type AnyPatternDefinition =\n\t| PatternDefinition\n\t| OrchestrationPatternDefinition;\n\nexport function isOrchestrationPattern(\n\tdef: AnyPatternDefinition,\n): def is OrchestrationPatternDefinition {\n\treturn (def as { kind?: PatternKind }).kind === 'orchestration';\n}\n\nexport function isDomainPattern(\n\tdef: AnyPatternDefinition,\n): def is PatternDefinition {\n\treturn !isOrchestrationPattern(def);\n}\n\n/**\n * Identity function that returns its argument unchanged — orchestration\n * counterpart to `definePattern()`. The body is trivial on purpose; the\n * point is to give TypeScript a hook so consumer fixtures get full\n * compile-time checking against `OrchestrationPatternDefinition`.\n */\nexport function defineOrchestrationPattern(\n\tdef: OrchestrationPatternDefinition,\n): OrchestrationPatternDefinition {\n\treturn def;\n}\n","/**\n * Pattern Composition Validator\n *\n * Enforces the ADR-031 composition rules against parsed entities:\n *\n * | Case | Result |\n * |------------------------------------------------------------|------------------------|\n * | Column conflict between two patterns | error |\n * | Column conflict with entity field | error |\n * | Column conflict with a behavior field | error |\n * | Method-name conflict between patterns | (TS compile error) |\n * | Same implied behavior across patterns | silent dedup |\n * | Pattern referenced in YAML but not in the registry | error |\n * | `config:` key for a pattern the entity is not using | warning |\n * | Pattern config fails its Zod schema | error |\n *\n * Method-name conflicts are explicitly **not** checked here — they surface as\n * TypeScript compile errors at the consumer when the generated concrete\n * class extends the base. Adding a codegen check would duplicate work\n * the type system already does, so we stay silent on that row per ADR-031.\n *\n * Project-level validation (`validatePatternProject`) covers plan Risk 4:\n * entities declaring `pattern:` while `generate.architecture: clean` is\n * selected get a warning since the `clean` pipeline does not yet consume\n * patterns. Additive Phase 3+ work per ADR.\n *\n * The shape mirrors `src/behaviors/index.ts:81–124` (`validateBehaviors`):\n * a single pass that returns structured issues for `analyzeDomain()` to\n * aggregate.\n */\n\nimport type { AnalysisIssue, ParsedEntity } from '../analyzer/types.js';\nimport { resolveBehaviorFields } from '../behaviors/index.js';\nimport { getPattern } from './registry.js';\n\n// ============================================================================\n// Per-entity validation\n// ============================================================================\n\n/**\n * Validate pattern composition for a single entity. Returns an array of\n * `AnalysisIssue` values suitable for concatenation into `analyzeDomain`'s\n * aggregated issue list.\n *\n * Entities with no `pattern:` or `patterns:` declared return an empty\n * array — pattern-free entities are a valid use case (plain `BaseRepository`\n * fallback) and nothing below applies to them.\n */\nexport function validatePatternComposition(\n\tentity: ParsedEntity,\n): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\t// Normalise `pattern:` (single) and `patterns:` (multi) into one list,\n\t// preserving declaration order. `pattern` + `patterns` mutual exclusion\n\t// is a schema-level check — by the time we get here, at most one shape\n\t// is set.\n\tconst patternNames: string[] = entity.patterns ?? (entity.pattern ? [entity.pattern] : []);\n\tif (patternNames.length === 0) return issues;\n\n\t// Column-source tracker: maps column name → human-readable origin.\n\t// Populated in priority order (entity fields > behavior fields >\n\t// pattern contributions) so conflict messages name the *existing*\n\t// contributor correctly.\n\tconst columnSources = new Map<string, string>();\n\n\tfor (const [name] of entity.fields) {\n\t\tcolumnSources.set(name, `entity field '${name}'`);\n\t}\n\n\t// Behavior fields participate in conflict detection. Behaviors the\n\t// entity has NOT already declared but that a pattern implies will be\n\t// added below (silent dedup); conflicts against those show up when\n\t// the pattern's columns are checked.\n\tconst behaviorFields = resolveBehaviorFields(entity.behaviors);\n\tfor (const bf of behaviorFields) {\n\t\tconst existing = columnSources.get(bf.name);\n\t\tif (existing) {\n\t\t\t// A behavior field colliding with an entity-declared field\n\t\t\t// was already a codegen problem before patterns existed. We\n\t\t\t// surface it here too so the composition check is the single\n\t\t\t// authoritative pass for \"column conflicts on this entity.\"\n\t\t\tissues.push({\n\t\t\t\tseverity: 'error',\n\t\t\t\ttype: 'pattern_column_conflict',\n\t\t\t\tentity: entity.name,\n\t\t\t\tmessage:\n\t\t\t\t\t`Behavior-contributed field '${bf.name}' conflicts with ${existing}.`,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tcolumnSources.set(bf.name, `behavior field '${bf.name}'`);\n\t}\n\n\t// Track implied behaviors across all declared patterns so we can\n\t// assert silent dedup rather than repeat issues — this also lets us\n\t// return the deduped list for callers that want to thread it into\n\t// template-locals later without re-walking.\n\tconst impliedBehaviors = new Set<string>(entity.behaviors);\n\n\tfor (const patternName of patternNames) {\n\t\tconst def = getPattern(patternName);\n\n\t\t// Rule: pattern referenced in YAML but not in the registry\n\t\tif (!def) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'error',\n\t\t\t\ttype: 'pattern_unknown',\n\t\t\t\tentity: entity.name,\n\t\t\t\tmessage:\n\t\t\t\t\t`Unknown pattern '${patternName}'. ` +\n\t\t\t\t\t`Library patterns are pre-registered; app patterns are loaded from ` +\n\t\t\t\t\t`globs in codegen.config.yaml 'patterns:' (default 'src/patterns/*.pattern.ts').`,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Rule: pattern config must match the pattern's Zod schema\n\t\tif (def.configSchema) {\n\t\t\tconst rawConfig = entity.patternConfig?.[patternName];\n\t\t\tconst result = def.configSchema.safeParse(rawConfig ?? {});\n\t\t\tif (!result.success) {\n\t\t\t\tconst detail = result.error.issues\n\t\t\t\t\t.map((i) => `${i.path.join('.') || '<root>'}: ${i.message}`)\n\t\t\t\t\t.join(', ');\n\t\t\t\tissues.push({\n\t\t\t\t\tseverity: 'error',\n\t\t\t\t\ttype: 'pattern_config_invalid',\n\t\t\t\t\tentity: entity.name,\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t`Pattern '${patternName}' config failed validation: ${detail}`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Rule: column contributions conflict with anything already in the\n\t\t// column-sources table. The first column to claim a name wins; the\n\t\t// second one reports the conflict naming both contributors.\n\t\tfor (const col of def.columns ?? []) {\n\t\t\tconst existing = columnSources.get(col.name);\n\t\t\tif (existing) {\n\t\t\t\tissues.push({\n\t\t\t\t\tseverity: 'error',\n\t\t\t\t\ttype: 'pattern_column_conflict',\n\t\t\t\t\tentity: entity.name,\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t`Pattern '${patternName}' contributes column '${col.name}' ` +\n\t\t\t\t\t\t`which conflicts with ${existing}.`,\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tcolumnSources.set(col.name, `pattern '${patternName}'`);\n\t\t}\n\n\t\t// Silent dedup on implied behaviors — a pattern declaring a\n\t\t// behavior the entity already has (or another pattern already\n\t\t// contributed) is a no-op, not an error.\n\t\tfor (const b of def.impliedBehaviors ?? []) {\n\t\t\timpliedBehaviors.add(b);\n\t\t}\n\t}\n\n\t// Rule: `config:` key for a pattern not in the declared list → warning.\n\tif (entity.patternConfig) {\n\t\tconst declared = new Set(patternNames);\n\t\tfor (const key of Object.keys(entity.patternConfig)) {\n\t\t\tif (!declared.has(key)) {\n\t\t\t\tissues.push({\n\t\t\t\t\tseverity: 'warning',\n\t\t\t\t\ttype: 'pattern_config_unused',\n\t\t\t\t\tentity: entity.name,\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t`Config block has key '${key}' but pattern '${key}' is not ` +\n\t\t\t\t\t\t`declared in 'pattern:' or 'patterns:'. Remove the entry or ` +\n\t\t\t\t\t\t`add the pattern.`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n// ============================================================================\n// Project-level validation — plan Risk 4\n// ============================================================================\n\nexport interface PatternProjectContext {\n\tentities: ReadonlyArray<ParsedEntity>;\n\t/**\n\t * Selected backend architecture from `codegen.config.yaml\n\t * generate.architecture`. `undefined` when the consumer is using the\n\t * library purely as an analyzer (no generation config loaded).\n\t */\n\tarchitecture?: string;\n}\n\n/**\n * Validate project-level invariants for patterns. Runs after\n * `validatePatternComposition` has visited every entity, so we can\n * assume per-entity errors have been surfaced.\n *\n * Today this only covers plan Risk 4: warn when patterns are declared\n * but the selected architecture is `clean`, which does not yet consume\n * them. A `clean` consumer with `pattern: Integrated` is not broken — the\n * `clean` pipeline ignores the key — but they see no effect, which is\n * confusing without the warning.\n */\nexport function validatePatternProject(\n\tctx: PatternProjectContext,\n): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\tif (ctx.architecture === 'clean') {\n\t\tconst withPatterns = ctx.entities.filter(\n\t\t\t(e) => (e.patterns && e.patterns.length > 0) || !!e.pattern,\n\t\t);\n\t\tfor (const e of withPatterns) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'warning',\n\t\t\t\ttype: 'pattern_clean_pipeline_noop',\n\t\t\t\tentity: e.name,\n\t\t\t\tmessage:\n\t\t\t\t\t`'pattern:' is declared but 'generate.architecture: clean' does not ` +\n\t\t\t\t\t`yet consume patterns. This declaration is a no-op. Patterns are ` +\n\t\t\t\t\t`consumed by 'clean-lite-ps' today; 'clean' integration is Phase 3+ ` +\n\t\t\t\t\t`additive work (ADR-031).`,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn issues;\n}\n","/**\n * Orchestration Pattern Validator (ADR-032)\n *\n * Project-level only — orchestration patterns are not entity-attached, so\n * there is no per-entity pass. Mirrors `validatePatternProject`'s shape:\n * one pure function consuming a context object and returning structured\n * `AnalysisIssue[]` for `analyzeDomain()` to aggregate.\n *\n * Enforces ADR-032 §\"Composition rules\" to the extent statically checkable\n * from a `OrchestrationPatternDefinition` alone:\n *\n * | Rule | Issue type |\n * |------------------------------------------------------------|-------------------------------------|\n * | Domain ↔ orchestration pattern share a name | pattern_name_collision |\n * | Registry has zero entries | pattern_entries_empty |\n * | Entry missing/non-string `key` or `provider` | pattern_entry_malformed |\n * | Two entries in the same registry share a `key` | pattern_entry_key_duplicate |\n * | Co-keyed registry's `keyType` diverges from the primary | pattern_cokeyed_keytype_mismatch |\n *\n * Two ADR-032 conflicts are NOT enforced here — they need consumer source\n * access that Phase 3-1 cannot do:\n * - `keyType`/`valueType` resolution (row 2): deferred to Phase 3-2 emission.\n * - Provider not exported by any known module (row 3): deferred to Phase 3-2\n * + DI runtime.\n *\n * Orchestration ↔ orchestration name duplicates ARE enforced — but at LOAD\n * time inside `loadAppPatterns()`, not here, because by the time the\n * validator runs the duplicate has already been deduped by `Map.set()`\n * keying on name. The loader emits a `LoadAppPatternsResult.errors` entry.\n */\n\nimport type { AnalysisIssue } from '../analyzer/types.js';\nimport type { OrchestrationPatternDefinition } from './pattern-definition.js';\n\n// Sentinel used for the `entity` field on project-level orchestration\n// issues. The orchestration kind is not entity-attached, so there is no\n// real entity name to point at. Existing console + markdown formatters\n// treat `issue.entity` as an opaque truthy string used only in display\n// (`${issue.entity}${issue.field ? '.' + issue.field : ''}`), so a\n// non-entity sentinel is safe — the formatters never look it up against\n// the parsed entity map.\nconst PROJECT_SENTINEL = '<project>';\n\nexport interface OrchestrationProjectContext {\n\t/** All orchestration patterns currently registered. */\n\torchestrationPatterns: ReadonlyArray<OrchestrationPatternDefinition>;\n\t/** All domain pattern names currently registered (library + app). */\n\tdomainPatternNames: ReadonlyArray<string>;\n}\n\nexport function validateOrchestrationProject(\n\tctx: OrchestrationProjectContext,\n): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\t// Rule 1: orchestration ↔ domain name collision (ADR-032 row 4).\n\tconst domainNameSet = new Set(ctx.domainPatternNames);\n\tfor (const orch of ctx.orchestrationPatterns) {\n\t\tif (domainNameSet.has(orch.name)) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'error',\n\t\t\t\ttype: 'pattern_name_collision',\n\t\t\t\tentity: PROJECT_SENTINEL,\n\t\t\t\tmessage:\n\t\t\t\t\t`Orchestration pattern '${orch.name}' shares a name with a domain ` +\n\t\t\t\t\t`pattern. Pattern names are globally unique across kinds (ADR-032 §Composition rules).`,\n\t\t\t});\n\t\t}\n\t}\n\n\t// Rules 2-4: per-pattern checks (entries shape + co-keyed keyType).\n\tfor (const orch of ctx.orchestrationPatterns) {\n\t\tconst allRegistries = [\n\t\t\torch.registry,\n\t\t\t...(orch.coKeyedRegistries ?? []),\n\t\t];\n\n\t\tfor (const reg of allRegistries) {\n\t\t\t// Rule 2: entries[] non-empty (defensive — loader already enforced\n\t\t\t// this for the primary registry, but co-keyed sibling registries\n\t\t\t// don't go through `assertOrchestrationContribution` and could be\n\t\t\t// authored as `entries: []`).\n\t\t\tif (!Array.isArray(reg.entries) || reg.entries.length === 0) {\n\t\t\t\tissues.push({\n\t\t\t\t\tseverity: 'error',\n\t\t\t\t\ttype: 'pattern_entries_empty',\n\t\t\t\t\tentity: PROJECT_SENTINEL,\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t`Orchestration pattern '${orch.name}' declares a registry with ` +\n\t\t\t\t\t\t`no entries. Provide at least one { key, provider } pair.`,\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Rules 3a + 3b: per-entry well-formedness + key uniqueness.\n\t\t\tconst seen = new Set<string>();\n\t\t\tfor (const entry of reg.entries) {\n\t\t\t\tif (typeof entry.key !== 'string' || entry.key.length === 0) {\n\t\t\t\t\tissues.push({\n\t\t\t\t\t\tseverity: 'error',\n\t\t\t\t\t\ttype: 'pattern_entry_malformed',\n\t\t\t\t\t\tentity: PROJECT_SENTINEL,\n\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\t`Orchestration pattern '${orch.name}' has an entry with a ` +\n\t\t\t\t\t\t\t`missing or non-string 'key'.`,\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (\n\t\t\t\t\ttypeof entry.provider !== 'string' ||\n\t\t\t\t\tentry.provider.length === 0\n\t\t\t\t) {\n\t\t\t\t\tissues.push({\n\t\t\t\t\t\tseverity: 'error',\n\t\t\t\t\t\ttype: 'pattern_entry_malformed',\n\t\t\t\t\t\tentity: PROJECT_SENTINEL,\n\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\t`Orchestration pattern '${orch.name}' entry '${entry.key}' has ` +\n\t\t\t\t\t\t\t`a missing or non-string 'provider'.`,\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (seen.has(entry.key)) {\n\t\t\t\t\tissues.push({\n\t\t\t\t\t\tseverity: 'error',\n\t\t\t\t\t\ttype: 'pattern_entry_key_duplicate',\n\t\t\t\t\t\tentity: PROJECT_SENTINEL,\n\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\t`Orchestration pattern '${orch.name}' has duplicate entry key ` +\n\t\t\t\t\t\t\t`'${entry.key}'. Keys must be unique within a registry.`,\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tseen.add(entry.key);\n\t\t\t}\n\t\t}\n\n\t\t// Rule 4: co-keyed registry keyType consistency (ADR-032 Decision 2).\n\t\tif (orch.coKeyedRegistries && orch.coKeyedRegistries.length > 0) {\n\t\t\tconst primaryKeyType = orch.registry.keyType;\n\t\t\tfor (const reg of orch.coKeyedRegistries) {\n\t\t\t\tif (reg.keyType !== primaryKeyType) {\n\t\t\t\t\tissues.push({\n\t\t\t\t\t\tseverity: 'error',\n\t\t\t\t\t\ttype: 'pattern_cokeyed_keytype_mismatch',\n\t\t\t\t\t\tentity: PROJECT_SENTINEL,\n\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\t`Orchestration pattern '${orch.name}' co-keyed registry has ` +\n\t\t\t\t\t\t\t`keyType '${reg.keyType}', expected '${primaryKeyType}'. ` +\n\t\t\t\t\t\t\t`Co-keyed registries must share the primary registry's key space (ADR-032 Decision 2).`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn issues;\n}\n","/**\n * Console Formatter\n *\n * Pretty terminal output with colors for the domain analysis results.\n */\n\nimport type { AnalysisResult, AnalysisIssue, Severity } from '../analyzer/types';\n\n// ANSI color codes\nconst colors = {\n\treset: '\\x1b[0m',\n\tbold: '\\x1b[1m',\n\tdim: '\\x1b[2m',\n\n\tred: '\\x1b[31m',\n\tgreen: '\\x1b[32m',\n\tyellow: '\\x1b[33m',\n\tblue: '\\x1b[34m',\n\tmagenta: '\\x1b[35m',\n\tcyan: '\\x1b[36m',\n\twhite: '\\x1b[37m',\n\n\tbgRed: '\\x1b[41m',\n\tbgGreen: '\\x1b[42m',\n\tbgYellow: '\\x1b[43m',\n};\n\nfunction color(text: string, ...styles: string[]): string {\n\treturn `${styles.join('')}${text}${colors.reset}`;\n}\n\nfunction severityColor(severity: Severity): string {\n\tswitch (severity) {\n\t\tcase 'error':\n\t\t\treturn colors.red;\n\t\tcase 'warning':\n\t\t\treturn colors.yellow;\n\t\tcase 'info':\n\t\t\treturn colors.cyan;\n\t}\n}\n\nfunction severityIcon(severity: Severity): string {\n\tswitch (severity) {\n\t\tcase 'error':\n\t\t\treturn 'X';\n\t\tcase 'warning':\n\t\t\treturn '!';\n\t\tcase 'info':\n\t\t\treturn 'i';\n\t}\n}\n\n/**\n * Format analysis result for console output\n */\nexport function formatConsole(result: AnalysisResult): string {\n\tconst lines: string[] = [];\n\n\t// Header\n\tlines.push('');\n\tlines.push(color('='.repeat(60), colors.dim));\n\tlines.push(color(' Domain Analysis Report', colors.bold, colors.cyan));\n\tlines.push(color('='.repeat(60), colors.dim));\n\tlines.push('');\n\n\t// Statistics\n\tlines.push(...formatStatistics(result));\n\n\t// Entity summary\n\tlines.push(...formatEntities(result));\n\n\t// Relationships\n\tlines.push(...formatRelationships(result));\n\n\t// Issues\n\tif (result.issues.length > 0) {\n\t\tlines.push(...formatIssues(result.issues));\n\t}\n\n\t// Final status\n\tlines.push('');\n\tlines.push(color('-'.repeat(60), colors.dim));\n\n\tconst errors = result.issues.filter((i) => i.severity === 'error');\n\tconst warnings = result.issues.filter((i) => i.severity === 'warning');\n\tconst infos = result.issues.filter((i) => i.severity === 'info');\n\n\tif (result.isValid) {\n\t\tlines.push(\n\t\t\tcolor(\n\t\t\t\t`[OK] Domain is valid (${warnings.length} warnings, ${infos.length} info)`,\n\t\t\t\tcolors.green\n\t\t\t)\n\t\t);\n\t} else {\n\t\tlines.push(color(`[FAIL] Domain has ${errors.length} errors`, colors.red));\n\t}\n\n\tlines.push(color('-'.repeat(60), colors.dim));\n\tlines.push('');\n\n\treturn lines.join('\\n');\n}\n\nfunction formatStatistics(result: AnalysisResult): string[] {\n\tconst lines: string[] = [];\n\tconst stats = result.statistics;\n\n\tlines.push(color('Statistics:', colors.bold));\n\tlines.push('');\n\tlines.push(` Entities: ${stats.totalEntities}`);\n\tlines.push(\n\t\t` Fields: ${stats.totalFields} (avg ${stats.averageFieldsPerEntity.toFixed(1)}/entity)`\n\t);\n\tlines.push(` Relationships: ${stats.totalRelationships}`);\n\tlines.push(` With behaviors: ${stats.entitiesWithBehaviors}`);\n\tlines.push('');\n\n\t// Field types breakdown\n\tlines.push(' Field types:');\n\tconst sortedTypes = Object.entries(stats.fieldsByType).sort((a, b) => b[1] - a[1]);\n\tfor (const [type, count] of sortedTypes) {\n\t\tconst bar = color('|'.repeat(Math.min(count, 20)), colors.blue);\n\t\tlines.push(` ${type.padEnd(12)} ${bar} ${count}`);\n\t}\n\tlines.push('');\n\n\t// Relationship types breakdown\n\tif (stats.totalRelationships > 0) {\n\t\tlines.push(' Relationship types:');\n\t\tconst sortedRels = Object.entries(stats.relationshipsByType).sort((a, b) => b[1] - a[1]);\n\t\tfor (const [type, count] of sortedRels) {\n\t\t\tconst bar = color('|'.repeat(Math.min(count, 20)), colors.magenta);\n\t\t\tlines.push(` ${type.padEnd(12)} ${bar} ${count}`);\n\t\t}\n\t\tlines.push('');\n\t}\n\n\treturn lines;\n}\n\nfunction formatEntities(result: AnalysisResult): string[] {\n\tconst lines: string[] = [];\n\n\tlines.push(color('Entities:', colors.bold));\n\tlines.push('');\n\n\tfor (const entity of result.entities) {\n\t\tconst fieldCount = entity.fields.size;\n\t\tconst relCount = entity.relationships.size;\n\t\tlines.push(\n\t\t\t` ${color(entity.name, colors.cyan)} (${fieldCount} fields, ${relCount} relationships)`\n\t\t);\n\t\tif (entity.behaviors.length > 0) {\n\t\t\tlines.push(color(` behaviors: ${entity.behaviors.join(', ')}`, colors.dim));\n\t\t}\n\t}\n\tlines.push('');\n\n\treturn lines;\n}\n\nfunction formatRelationships(result: AnalysisResult): string[] {\n\tconst lines: string[] = [];\n\n\tif (result.graph.edges.length === 0) {\n\t\treturn lines;\n\t}\n\n\tlines.push(color('Relationships:', colors.bold));\n\tlines.push('');\n\n\tfor (const edge of result.graph.edges) {\n\t\tconst arrow = getCardinalityArrow(edge.cardinality);\n\t\tconst bidir = edge.bidirectional ? color(' (bidirectional)', colors.dim) : '';\n\t\tlines.push(\n\t\t\t` ${edge.from.padEnd(20)} ${arrow} ${edge.to} ${color(`(${edge.relationship.type})`, colors.dim)}${bidir}`\n\t\t);\n\t}\n\tlines.push('');\n\n\treturn lines;\n}\n\nfunction getCardinalityArrow(cardinality: string): string {\n\tswitch (cardinality) {\n\t\tcase '1:N':\n\t\t\treturn color('--<', colors.magenta);\n\t\tcase 'N:1':\n\t\t\treturn color('>--', colors.magenta);\n\t\tcase '1:1':\n\t\t\treturn color('---', colors.magenta);\n\t\tcase 'N:M':\n\t\t\treturn color('>-<', colors.magenta);\n\t\tdefault:\n\t\t\treturn color('-->', colors.magenta);\n\t}\n}\n\nfunction formatIssues(issues: AnalysisIssue[]): string[] {\n\tconst lines: string[] = [];\n\n\t// Group by severity\n\tconst errors = issues.filter((i) => i.severity === 'error');\n\tconst warnings = issues.filter((i) => i.severity === 'warning');\n\tconst infos = issues.filter((i) => i.severity === 'info');\n\n\tif (errors.length > 0) {\n\t\tlines.push(color(`Errors (${errors.length}):`, colors.bold, colors.red));\n\t\tlines.push('');\n\t\tlines.push(...formatIssueList(errors, 'error'));\n\t\tlines.push('');\n\t}\n\n\tif (warnings.length > 0) {\n\t\tlines.push(color(`Warnings (${warnings.length}):`, colors.bold, colors.yellow));\n\t\tlines.push('');\n\t\tlines.push(...formatIssueList(warnings, 'warning'));\n\t\tlines.push('');\n\t}\n\n\tif (infos.length > 0) {\n\t\tlines.push(color(`Info (${infos.length}):`, colors.bold, colors.cyan));\n\t\tlines.push('');\n\t\tlines.push(...formatIssueList(infos, 'info', 5)); // Only show first 5 info messages\n\t\tlines.push('');\n\t}\n\n\treturn lines;\n}\n\nfunction formatIssueList(\n\tissues: AnalysisIssue[],\n\tseverity: Severity,\n\tlimit?: number\n): string[] {\n\tconst lines: string[] = [];\n\tconst displayIssues = limit ? issues.slice(0, limit) : issues;\n\n\t// Group by type\n\tconst byType = new Map<string, AnalysisIssue[]>();\n\tfor (const issue of displayIssues) {\n\t\tconst list = byType.get(issue.type) ?? [];\n\t\tlist.push(issue);\n\t\tbyType.set(issue.type, list);\n\t}\n\n\tfor (const [type, typeIssues] of byType) {\n\t\tlines.push(color(` ${type} (${typeIssues.length}):`, colors.dim));\n\n\t\tfor (const issue of typeIssues.slice(0, 5)) {\n\t\t\tconst location = issue.entity\n\t\t\t\t? `${issue.entity}${issue.field ? '.' + issue.field : ''}`\n\t\t\t\t: issue.path ?? 'unknown';\n\n\t\t\tconst icon = color(`[${severityIcon(severity)}]`, severityColor(severity));\n\t\t\tlines.push(` ${icon} ${color(location, colors.bold)}: ${issue.message}`);\n\n\t\t\tif (issue.suggestion) {\n\t\t\t\tlines.push(color(` -> ${issue.suggestion}`, colors.dim));\n\t\t\t}\n\t\t}\n\n\t\tif (typeIssues.length > 5) {\n\t\t\tlines.push(color(` ... and ${typeIssues.length - 5} more`, colors.dim));\n\t\t}\n\t}\n\n\tif (limit && issues.length > limit) {\n\t\tlines.push(color(` ... and ${issues.length - limit} more info messages`, colors.dim));\n\t}\n\n\treturn lines;\n}\n","/**\n * JSON Formatter\n *\n * Machine-readable JSON output for the domain analysis results.\n */\n\nimport type { AnalysisResult, ParsedEntity, DomainGraph } from '../analyzer/types';\n\n/**\n * Helper to convert Maps to plain objects for JSON serialization\n */\nfunction mapToObject<K extends string, V>(map: Map<K, V>): Record<K, V> {\n\tconst obj = {} as Record<K, V>;\n\tfor (const [key, value] of map) {\n\t\tobj[key] = value;\n\t}\n\treturn obj;\n}\n\n/**\n * Convert ParsedEntity to a JSON-serializable format\n */\nfunction serializeEntity(entity: ParsedEntity): Record<string, unknown> {\n\treturn {\n\t\tname: entity.name,\n\t\tplural: entity.plural,\n\t\ttable: entity.table,\n\t\tfolderStructure: entity.folderStructure,\n\t\tfields: mapToObject(entity.fields),\n\t\trelationships: mapToObject(entity.relationships),\n\t\tbehaviors: entity.behaviors,\n\t\tsourcePath: entity.sourcePath,\n\t};\n}\n\n/**\n * Convert DomainGraph to a JSON-serializable format\n */\nfunction serializeGraph(graph: DomainGraph): Record<string, unknown> {\n\tconst entities: Record<string, unknown> = {};\n\tfor (const [name, entity] of graph.entities) {\n\t\tentities[name] = serializeEntity(entity);\n\t}\n\n\treturn {\n\t\tentities,\n\t\tedges: graph.edges,\n\t};\n}\n\n/**\n * Format analysis result as JSON string\n */\nexport function formatJson(result: AnalysisResult, pretty = true): string {\n\tconst output = {\n\t\tisValid: result.isValid,\n\t\tsummary: {\n\t\t\tentities: result.statistics.totalEntities,\n\t\t\tfields: result.statistics.totalFields,\n\t\t\trelationships: result.statistics.totalRelationships,\n\t\t\terrors: result.issues.filter((i) => i.severity === 'error').length,\n\t\t\twarnings: result.issues.filter((i) => i.severity === 'warning').length,\n\t\t\tinfo: result.issues.filter((i) => i.severity === 'info').length,\n\t\t},\n\t\tentities: result.entities.map(serializeEntity),\n\t\tgraph: serializeGraph(result.graph),\n\t\tissues: result.issues,\n\t\tstatistics: result.statistics,\n\t\ttimestamp: new Date().toISOString(),\n\t};\n\n\treturn pretty ? JSON.stringify(output, null, 2) : JSON.stringify(output);\n}\n\n/**\n * Format only statistics as JSON\n */\nexport function formatStatsJson(result: AnalysisResult, pretty = true): string {\n\tconst output = {\n\t\tstatistics: result.statistics,\n\t\tisValid: result.isValid,\n\t\tissueCount: {\n\t\t\terrors: result.issues.filter((i) => i.severity === 'error').length,\n\t\t\twarnings: result.issues.filter((i) => i.severity === 'warning').length,\n\t\t\tinfo: result.issues.filter((i) => i.severity === 'info').length,\n\t\t},\n\t\ttimestamp: new Date().toISOString(),\n\t};\n\n\treturn pretty ? JSON.stringify(output, null, 2) : JSON.stringify(output);\n}\n\n/**\n * Format only issues as JSON\n */\nexport function formatIssuesJson(result: AnalysisResult, pretty = true): string {\n\tconst output = {\n\t\tisValid: result.isValid,\n\t\tissues: result.issues,\n\t\ttimestamp: new Date().toISOString(),\n\t};\n\n\treturn pretty ? JSON.stringify(output, null, 2) : JSON.stringify(output);\n}\n","/**\n * Markdown Formatter\n *\n * Documentation output with Mermaid diagrams for the domain analysis results.\n */\n\nimport type { AnalysisResult, ParsedEntity, RelationshipEdge } from '../analyzer/types';\n\n/**\n * Format analysis result as Markdown documentation\n */\nexport function formatMarkdown(result: AnalysisResult): string {\n\tconst lines: string[] = [];\n\n\t// Title\n\tlines.push('# Domain Model Documentation');\n\tlines.push('');\n\tlines.push(`Generated: ${new Date().toISOString()}`);\n\tlines.push('');\n\n\t// Overview statistics\n\tlines.push('## Overview');\n\tlines.push('');\n\tlines.push('| Metric | Value |');\n\tlines.push('|--------|-------|');\n\tlines.push(`| Entities | ${result.statistics.totalEntities} |`);\n\tlines.push(`| Total Fields | ${result.statistics.totalFields} |`);\n\tlines.push(`| Total Relationships | ${result.statistics.totalRelationships} |`);\n\tlines.push(\n\t\t`| Avg Fields/Entity | ${result.statistics.averageFieldsPerEntity.toFixed(1)} |`\n\t);\n\tlines.push('');\n\n\t// Field type distribution\n\tlines.push('### Field Type Distribution');\n\tlines.push('');\n\tlines.push('| Type | Count |');\n\tlines.push('|------|-------|');\n\tconst sortedTypes = Object.entries(result.statistics.fieldsByType).sort(\n\t\t(a, b) => b[1] - a[1]\n\t);\n\tfor (const [type, count] of sortedTypes) {\n\t\tlines.push(`| ${type} | ${count} |`);\n\t}\n\tlines.push('');\n\n\t// Relationship type distribution\n\tif (result.statistics.totalRelationships > 0) {\n\t\tlines.push('### Relationship Type Distribution');\n\t\tlines.push('');\n\t\tlines.push('| Type | Count |');\n\t\tlines.push('|------|-------|');\n\t\tconst sortedRels = Object.entries(result.statistics.relationshipsByType).sort(\n\t\t\t(a, b) => b[1] - a[1]\n\t\t);\n\t\tfor (const [type, count] of sortedRels) {\n\t\t\tlines.push(`| ${type} | ${count} |`);\n\t\t}\n\t\tlines.push('');\n\t}\n\n\t// Entity Relationship Diagram\n\tlines.push('## Entity Relationship Diagram');\n\tlines.push('');\n\tlines.push('```mermaid');\n\tlines.push(...generateMermaidErDiagram(result));\n\tlines.push('```');\n\tlines.push('');\n\n\t// Entities\n\tlines.push('## Entities');\n\tlines.push('');\n\n\tfor (const entity of result.entities) {\n\t\tlines.push(...formatEntitySection(entity));\n\t}\n\n\t// Issues\n\tconst errors = result.issues.filter((i) => i.severity === 'error');\n\tconst warnings = result.issues.filter((i) => i.severity === 'warning');\n\tconst infos = result.issues.filter((i) => i.severity === 'info');\n\n\tif (result.issues.length > 0) {\n\t\tlines.push('## Analysis Issues');\n\t\tlines.push('');\n\n\t\tif (errors.length > 0) {\n\t\t\tlines.push('### Errors');\n\t\t\tlines.push('');\n\t\t\tfor (const issue of errors) {\n\t\t\t\tconst location = issue.entity\n\t\t\t\t\t? `**${issue.entity}${issue.field ? '.' + issue.field : ''}**`\n\t\t\t\t\t: issue.path ?? 'unknown';\n\t\t\t\tlines.push(`- [${issue.type}] ${location}: ${issue.message}`);\n\t\t\t\tif (issue.suggestion) {\n\t\t\t\t\tlines.push(` - Suggestion: ${issue.suggestion}`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tlines.push('');\n\t\t}\n\n\t\tif (warnings.length > 0) {\n\t\t\tlines.push('### Warnings');\n\t\t\tlines.push('');\n\t\t\tfor (const issue of warnings) {\n\t\t\t\tconst location = issue.entity\n\t\t\t\t\t? `**${issue.entity}${issue.field ? '.' + issue.field : ''}**`\n\t\t\t\t\t: issue.path ?? 'unknown';\n\t\t\t\tlines.push(`- [${issue.type}] ${location}: ${issue.message}`);\n\t\t\t\tif (issue.suggestion) {\n\t\t\t\t\tlines.push(` - Suggestion: ${issue.suggestion}`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tlines.push('');\n\t\t}\n\n\t\tif (infos.length > 0) {\n\t\t\tlines.push('### Info');\n\t\t\tlines.push('');\n\t\t\tlines.push('<details>');\n\t\t\tlines.push('<summary>Show info messages</summary>');\n\t\t\tlines.push('');\n\t\t\tfor (const issue of infos) {\n\t\t\t\tconst location = issue.entity\n\t\t\t\t\t? `**${issue.entity}${issue.field ? '.' + issue.field : ''}**`\n\t\t\t\t\t: issue.path ?? 'unknown';\n\t\t\t\tlines.push(`- [${issue.type}] ${location}: ${issue.message}`);\n\t\t\t}\n\t\t\tlines.push('');\n\t\t\tlines.push('</details>');\n\t\t\tlines.push('');\n\t\t}\n\t}\n\n\treturn lines.join('\\n');\n}\n\n/**\n * Format a single entity section\n */\nfunction formatEntitySection(entity: ParsedEntity): string[] {\n\tconst lines: string[] = [];\n\n\tlines.push(`### ${entity.name}`);\n\tlines.push('');\n\tlines.push(`**Table:** \\`${entity.table}\\``);\n\tlines.push(`**Plural:** ${entity.plural}`);\n\tif (entity.behaviors.length > 0) {\n\t\tlines.push(`**Behaviors:** ${entity.behaviors.join(', ')}`);\n\t}\n\tlines.push('');\n\n\t// Fields table\n\tlines.push('#### Fields');\n\tlines.push('');\n\tlines.push('| Name | Type | Required | Nullable | Index | Foreign Key |');\n\tlines.push('|------|------|----------|----------|-------|-------------|');\n\n\tfor (const [name, field] of entity.fields) {\n\t\tconst required = field.required ? 'Yes' : '';\n\t\tconst nullable = field.nullable ? 'Yes' : '';\n\t\tconst index = field.index ? 'Yes' : field.unique ? 'Unique' : '';\n\t\tconst fk = field.foreignKey ? `${field.foreignKey.table}.${field.foreignKey.column}` : '';\n\t\tlines.push(`| ${name} | ${field.type} | ${required} | ${nullable} | ${index} | ${fk} |`);\n\t}\n\tlines.push('');\n\n\t// Relationships\n\tif (entity.relationships.size > 0) {\n\t\tlines.push('#### Relationships');\n\t\tlines.push('');\n\t\tlines.push('| Name | Type | Target | Foreign Key |');\n\t\tlines.push('|------|------|--------|-------------|');\n\n\t\tfor (const [name, rel] of entity.relationships) {\n\t\t\tlines.push(`| ${name} | ${rel.type} | ${rel.target} | ${rel.foreignKey} |`);\n\t\t}\n\t\tlines.push('');\n\t}\n\n\treturn lines;\n}\n\n/**\n * Generate Mermaid ER diagram\n */\nfunction generateMermaidErDiagram(result: AnalysisResult): string[] {\n\tconst lines: string[] = [];\n\n\tlines.push('erDiagram');\n\n\t// Define entities with their fields\n\tfor (const entity of result.entities) {\n\t\tconst entityName = entity.name.toUpperCase();\n\t\tlines.push(` ${entityName} {`);\n\n\t\t// Show key fields only (to keep diagram readable)\n\t\tconst keyFields = Array.from(entity.fields.entries())\n\t\t\t.filter(\n\t\t\t\t([name, field]) =>\n\t\t\t\t\tfield.foreignKey || field.unique || field.index || name === 'id' || name === 'name'\n\t\t\t)\n\t\t\t.slice(0, 6); // Limit to 6 fields\n\n\t\tfor (const [name, field] of keyFields) {\n\t\t\tconst typeStr = field.type;\n\t\t\tconst pk = name === 'id' ? 'PK' : '';\n\t\t\tconst fk = field.foreignKey ? 'FK' : '';\n\t\t\tconst marker = pk || fk ? ` \"${pk}${fk}\"` : '';\n\t\t\tlines.push(` ${typeStr} ${name}${marker}`);\n\t\t}\n\n\t\tif (entity.fields.size > keyFields.length) {\n\t\t\tlines.push(` string _more_fields`);\n\t\t}\n\n\t\tlines.push(' }');\n\t}\n\n\t// Add relationships\n\tfor (const edge of result.graph.edges) {\n\t\tconst from = edge.from.toUpperCase();\n\t\tconst to = edge.to.toUpperCase();\n\t\tconst cardinalitySymbol = getCardinalitySymbol(edge.cardinality);\n\t\tconst label = edge.relationship.name;\n\n\t\tlines.push(` ${from} ${cardinalitySymbol} ${to} : \"${label}\"`);\n\t}\n\n\treturn lines;\n}\n\n/**\n * Get Mermaid cardinality symbol\n */\nfunction getCardinalitySymbol(cardinality: string): string {\n\tswitch (cardinality) {\n\t\tcase '1:N':\n\t\t\treturn '||--o{';\n\t\tcase 'N:1':\n\t\t\treturn '}o--||';\n\t\tcase '1:1':\n\t\t\treturn '||--||';\n\t\tcase 'N:M':\n\t\t\treturn '}o--o{';\n\t\tdefault:\n\t\t\treturn '||--o{';\n\t}\n}\n\n/**\n * Generate a simple relationship graph in Mermaid\n */\nexport function formatMermaidGraph(result: AnalysisResult): string {\n\tconst lines: string[] = [];\n\n\tlines.push('```mermaid');\n\tlines.push('graph LR');\n\n\t// Style definitions\n\tlines.push(' classDef entity fill:#e1f5fe,stroke:#01579b');\n\n\t// Add entities as nodes\n\tfor (const entity of result.entities) {\n\t\tlines.push(` ${entity.name}[\"${entity.name}\\\\n(${entity.fields.size} fields)\"]`);\n\t}\n\n\t// Add relationships as edges\n\tfor (const edge of result.graph.edges) {\n\t\tconst style = edge.bidirectional ? '<-->' : '-->';\n\t\tlines.push(` ${edge.from} ${style}|${edge.relationship.type}| ${edge.to}`);\n\t}\n\n\t// Apply styles\n\tconst entityList = result.entities.map((e) => e.name).join(',');\n\tif (entityList) {\n\t\tlines.push(` class ${entityList} entity`);\n\t}\n\n\tlines.push('```');\n\n\treturn lines.join('\\n');\n}\n","/**\n * ActivityPattern — config-driven subject-scoped interaction base.\n *\n * Activity entities represent interactions (calls, meetings, emails, messages,\n * transcripts) that reference a *subject* — the thing the interaction is about.\n * Which subject is a per-entity fact, not a library constant: a CRM activity is\n * scoped to an `opportunity`, a swe-brain interaction to a `person` (later\n * `repo`/`team`, ADR-0006's Salesforce Activities-vs-Records shape). The base\n * repository/service therefore expose **generic** subject-scoped finders\n * (`findBySubjectId` / `findRecentBySubjectId`) that read the subject FK column\n * from the entity's `config:` block, on top of the standard CRUD methods plus\n * date-range and actor (`user_id`) scoping.\n *\n * The subject FK column resolves from `config: { Activity: { ... } }`:\n * - `subjectColumn` — explicit snake_case column, OR\n * - `<subject>_id` — derived from the `subject` entity name.\n * The recency-ordering column is `occurredAt` (snake_case in config), default\n * `occurred_at`. The base reads these via `this.patternConfig` — the same\n * ADR-031 §4 hand-off `IntegratedEntityRepository` uses for `integrationConfig`.\n *\n * See `docs/specs/ACTIVITY-SUBJECT-1.md`.\n */\n\nimport { z } from 'zod';\nimport { definePattern } from '../pattern-definition.js';\n\n/**\n * Per-entity `config: { Activity: {...} }` block, validated at parse time.\n * All fields optional — a date/user-only Activity entity supplies no config\n * (and the subject finders throw if called). `.strict()` rejects misspelled\n * keys loudly, matching JunctionPattern.\n */\nconst ActivityPatternConfigSchema = z\n\t.object({\n\t\t/** Subject entity name → derives the FK column `<subject>_id`. */\n\t\tsubject: z.string().optional(),\n\t\t/** Explicit snake_case FK column, when it does not follow `<subject>_id`. */\n\t\tsubjectColumn: z.string().optional(),\n\t\t/** snake_case recency-ordering column; defaults to `occurred_at`. */\n\t\toccurredAt: z.string().optional(),\n\t})\n\t.strict();\n\nexport const ActivityPattern = definePattern({\n\tname: 'Activity',\n\textends: ['Base'],\n\trepositoryClass: 'ActivityEntityRepository',\n\tserviceClass: 'ActivityEntityService',\n\trepositoryImport: '@shared/base-classes/activity-entity-repository',\n\tserviceImport: '@shared/base-classes/activity-entity-service',\n\tconfigSchema: ActivityPatternConfigSchema,\n\trepositoryInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete, upsertMany',\n\t\t'findByDateRange, findByUserId, findBySubjectId, findRecentBySubjectId',\n\t],\n\tserviceInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete',\n\t\t'findByDateRange, findByUser, findBySubject, findRecent',\n\t],\n\tdescription:\n\t\t'Subject-scoped interaction entities — date-range + actor + config-driven subject lookups',\n});\n","/**\n * BasePattern — identity pattern for the `extends` chain.\n *\n * Contributes no columns, no implied behaviors, and no config. Its only\n * purpose is to anchor the inheritance hierarchy so every other pattern\n * can declare `extends: ['Base']` and codegen can resolve that to a\n * concrete `BaseRepository` / `BaseService` reference.\n *\n * Matches the existing `family: base` entry in\n * `templates/entity/new/clean-lite-ps/prompt-extension.js` verbatim.\n */\n\nimport { definePattern } from '../pattern-definition.js';\n\nexport const BasePattern = definePattern({\n\tname: 'Base',\n\trepositoryClass: 'BaseRepository',\n\tserviceClass: 'BaseService',\n\trepositoryImport: '@shared/base-classes/base-repository',\n\tserviceImport: '@shared/base-classes/base-service',\n\trepositoryInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete, upsertMany',\n\t],\n\tserviceInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete',\n\t],\n\tdescription: 'Identity pattern — base CRUD, no extra columns or methods',\n});\n","/**\n * JunctionPattern — top-level discriminator for explicit many-to-many\n * junction YAML files.\n *\n * Unlike `Activity` / `Integrated` / `Metadata` (which attach to an entity via\n * `pattern:` / `patterns:`), `Junction` IS the top-level YAML shape — a\n * junction file's discriminator is `pattern: Junction`, not `entity:`.\n * It therefore does not declare `repositoryClass` / `serviceClass`: the\n * downstream Hygen-template leaf emits a dedicated junction repo/service\n * per pairing.\n *\n * `columns` is set to `BaseJunctionFields` for two reasons:\n * 1. Registry-side declaration of the shared shape — discoverable through\n * `getPattern('Junction').columns` by the downstream template leaf.\n * 2. Satisfies the registry's `assertHasContribution()` check, which\n * insists every pattern contribute at least one of columns / repo /\n * service class. (See spec §\"Open Questions Q3\"; recommendation (a).)\n *\n * See `.ai-docs/stacks/codegen-app-patterns/specs/58.md`.\n */\n\nimport { z } from 'zod';\nimport { definePattern } from '../pattern-definition.js';\nimport { BaseJunctionFields } from './base-junction-fields.js';\n\n/**\n * The `pattern: Junction`-attached config block, validated at parse time.\n *\n * Surface is intentionally thin in this leaf — extensions land in later\n * leaves (templates, association-codegen). `.strict()` rejects unknown\n * keys so consumers who misspell a flag fail loudly.\n */\nconst JunctionPatternConfigSchema = z.object({}).strict();\n\nexport const JunctionPattern = definePattern({\n\tname: 'Junction',\n\tdescription:\n\t\t'Explicit many-to-many junction with role + temporal + sourcing metadata',\n\tcolumns: [...BaseJunctionFields],\n\tconfigSchema: JunctionPatternConfigSchema,\n});\n","/**\n * KnowledgePattern — replaces `family: knowledge`.\n *\n * Knowledge entities hold long-form content with a workflow status and\n * semantic-search support (vectors, pending/approved states). The base\n * classes expose `semanticSearch`, pending-by-opportunity lookups, and\n * batch status updates.\n *\n * Class names, import paths, and inherited-method strings match the\n * legacy `FAMILY_MAP` entry verbatim.\n */\n\nimport { definePattern } from '../pattern-definition.js';\n\nexport const KnowledgePattern = definePattern({\n\tname: 'Knowledge',\n\textends: ['Base'],\n\trepositoryClass: 'KnowledgeEntityRepository',\n\tserviceClass: 'KnowledgeEntityService',\n\trepositoryImport: '@shared/base-classes/knowledge-entity-repository',\n\tserviceImport: '@shared/base-classes/knowledge-entity-service',\n\trepositoryInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete, upsertMany',\n\t\t'semanticSearch, findPendingByOpportunityId, updateStatus, updateStatusBatch',\n\t],\n\tserviceInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete',\n\t\t'semanticSearch, findPendingByOpportunityId, updateStatus, updateStatusBatch',\n\t],\n\tdescription: 'Knowledge entities — semantic search + workflow status',\n});\n","/**\n * MetadataPattern — replaces `family: metadata`.\n *\n * Metadata entities represent history-tracked auxiliary rows attached to a\n * parent entity (audit trails, custom-field values, change logs). The base\n * classes expose entity-id + type scoped lookups and history listing.\n *\n * Class names, import paths, and inherited-method strings match the\n * legacy `FAMILY_MAP` entry verbatim.\n */\n\nimport { definePattern } from '../pattern-definition.js';\n\nexport const MetadataPattern = definePattern({\n\tname: 'Metadata',\n\textends: ['Base'],\n\trepositoryClass: 'MetadataEntityRepository',\n\tserviceClass: 'MetadataEntityService',\n\trepositoryImport: '@shared/base-classes/metadata-entity-repository',\n\tserviceImport: '@shared/base-classes/metadata-entity-service',\n\trepositoryInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete, upsertMany',\n\t\t'findByEntityIdAndType, listByEntityId, listHistoryByEntityId',\n\t],\n\tserviceInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete',\n\t\t'findByEntityIdAndType, listByEntityId, listHistoryByEntityId',\n\t],\n\tdescription:\n\t\t'History-tracked metadata rows — entity-id + type scoped lookups',\n});\n","/**\n * IntegratedPattern — adds external-system integration columns and methods.\n *\n * Replaces the legacy `family: integrated` entry in\n * `templates/entity/new/clean-lite-ps/prompt-extension.js`. Class names,\n * import paths, and inherited-method comment lines are preserved verbatim\n * so PATTERN-5's template swap produces byte-identical output for\n * pre-existing `family: integrated` fixtures.\n *\n * Implies `external_id_tracking` — the behavior that contributes the\n * `external_id`, `provider`, and `provider_metadata` columns to the table.\n * An entity declaring `pattern: Integrated` need not re-declare the behavior.\n */\n\nimport { definePattern } from '../pattern-definition.js';\n\nexport const IntegratedPattern = definePattern({\n\tname: 'Integrated',\n\textends: ['Base'],\n\trepositoryClass: 'IntegratedEntityRepository',\n\tserviceClass: 'IntegratedEntityService',\n\trepositoryImport: '@shared/base-classes/integrated-entity-repository',\n\tserviceImport: '@shared/base-classes/integrated-entity-service',\n\trepositoryInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete, upsertMany',\n\t\t'findByExternalId, findManyByExternalIds, findAllByUserId, findVisibleByUserId',\n\t\t'integrationUpsertOne, findByExternalIdProjected, softDeleteByExternalId, integrationUpsert',\n\t],\n\tserviceInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete',\n\t\t'findByExternalId, findAllByUserId, findVisibleByUserId',\n\t],\n\timpliedBehaviors: ['external_id_tracking'],\n\tdescription: 'External CRM/system integration columns and integrationUpsert methods',\n});\n","/**\n * Library pattern bootstrap — imports every shipped pattern and registers\n * it with the shared library registry. Side-effect-only module: importing\n * this barrel is what pre-registers `Base`, `Integrated`, `Activity`,\n * `Knowledge`, and `Metadata`.\n *\n * Adding a new library pattern is two edits: create the `*.pattern.ts`\n * file and add the import+register pair below.\n */\n\nimport { registerLibraryPattern } from '../registry.js';\nimport { ActivityPattern } from './activity.pattern.js';\nimport { BasePattern } from './base.pattern.js';\nimport { JunctionPattern } from './junction.pattern.js';\nimport { KnowledgePattern } from './knowledge.pattern.js';\nimport { MetadataPattern } from './metadata.pattern.js';\nimport { IntegratedPattern } from './integrated.pattern.js';\n\nregisterLibraryPattern(BasePattern);\nregisterLibraryPattern(IntegratedPattern);\nregisterLibraryPattern(ActivityPattern);\nregisterLibraryPattern(KnowledgePattern);\nregisterLibraryPattern(MetadataPattern);\nregisterLibraryPattern(JunctionPattern);\n\nexport {\n\tActivityPattern,\n\tBasePattern,\n\tJunctionPattern,\n\tKnowledgePattern,\n\tMetadataPattern,\n\tIntegratedPattern,\n};\nexport {\n\tBaseJunctionFields,\n\tBASE_JUNCTION_FIELD_NAMES,\n} from './base-junction-fields.js';\n","/**\n * Frontend emitter — field UI-metadata derivation (ADR-038, FE-3).\n *\n * Ports the UI-inference helpers from the deleted `templates/entity/new/prompt.js`\n * (`inferUiType`, `inferUiImportance`, `formatLabel`, the entity_ref skip rules,\n * the choices/FK handling) into pure functions over `ParsedField`. The fields\n * emitter (`emit-fields.ts`) consumes these to build the `FieldMeta` objects the\n * old `fields.ejs.t` template emitted — same output contract.\n *\n * Naming for FK `reference` and belongs_to rows comes from the registry, never\n * re-pluralized here (the one place pts/prompt.js diverged; FE-1/FE-3 unify on\n * the registry).\n */\n\nimport type { ParsedField } from '../../analyzer/types';\n\n/** House default for the string→textarea max_length cutoff. */\nexport const DEFAULT_TEXTAREA_THRESHOLD = 500;\n\n/**\n * Knobs for the UI-type inference ladder (from `frontend.fields` config).\n *\n * `textareaThreshold`:\n * - `undefined` (absent) → use {@link DEFAULT_TEXTAREA_THRESHOLD} (500).\n * - explicit number → custom cutoff; `maxLength` must *strictly exceed* it.\n * - explicit `null` → heuristic disabled; bounded strings stay `text` unless\n * the author sets `ui_type: textarea`.\n */\nexport interface InferenceOptions {\n\t/** string→textarea cutoff; null disables the heuristic; undefined ⇒ DEFAULT_TEXTAREA_THRESHOLD. */\n\ttextareaThreshold?: number | null;\n}\n\n/** UI field type vocabulary (matches the old `FieldType` union). */\nexport type FieldType =\n\t| 'text'\n\t| 'textarea'\n\t| 'number'\n\t| 'boolean'\n\t| 'date'\n\t| 'datetime'\n\t| 'email'\n\t| 'url'\n\t| 'password'\n\t| 'money'\n\t| 'percentage'\n\t| 'json'\n\t| 'enum'\n\t| 'reference'\n\t| 'entity';\n\n/** UI importance tiers (matches the old `FieldImportance` union). */\nexport type FieldImportance = 'primary' | 'secondary' | 'tertiary';\n\n/**\n * Derived UI metadata for one field — the shape the fields emitter renders into\n * a `FieldMeta` object. Optional keys are present only when the field has them\n * (so the emitter can omit empty keys, matching the template's conditional\n * emission).\n *\n * The full YAML `ui_*` hint surface passes through (ADR-040): `group`,\n * `visible`, `placeholder`, `help`, and `format` come straight from the\n * author's YAML; `isKeyField`/`keyFieldOrder` carry key-field curation\n * (`ui_key_field` / `ui_key_field_order`) under the qField / EAV\n * `field_definitions` names so all three homes share one vocabulary.\n */\nexport interface DerivedFieldMeta {\n\tfield: string; // camelCase property name\n\tlabel: string;\n\ttype: FieldType;\n\timportance: FieldImportance;\n\tsortable: boolean;\n\tfilterable: boolean;\n\tgroup?: string;\n\tvisible?: boolean;\n\tplaceholder?: string;\n\thelp?: string;\n\tformat?: Record<string, unknown>;\n\tchoices?: string[];\n\treference?: string; // FK target table (from foreign_key)\n\tisKeyField?: boolean;\n\tkeyFieldOrder?: number;\n}\n\n/**\n * Derivation defaults a caller can supply from entity-level context (the\n * external-sync bundle in `emit-fields.ts` is the one current user). Author\n * YAML always wins over a default — these fill gaps, never override.\n */\nexport interface FieldMetaDefaults {\n\tgroup?: string;\n}\n\nconst CAMEL = (s: string): string =>\n\ts.replace(/_([a-z])/g, (_, c: string) => c.toUpperCase());\n\n/**\n * Humanize a snake_case field name into a Title Case label\n * (`first_name` → `First Name`). Ported from prompt.js `formatLabel`.\n */\nexport function formatLabel(fieldName: string): string {\n\treturn fieldName.replace(/_/g, ' ').replace(/\\b\\w/g, (c) => c.toUpperCase());\n}\n\n/**\n * Infer the UI type from a field. Explicit `ui.type` wins; then choices → enum,\n * FK → reference, name-pattern heuristics (email/url/password/money/percentage),\n * then the base-type map (string → text/textarea by max_length, etc).\n * Ported from prompt.js `inferUiType`.\n *\n * @param opts - Inference knobs; see {@link InferenceOptions}. Defaults to\n * {@link DEFAULT_TEXTAREA_THRESHOLD} (500) when `textareaThreshold` is absent.\n */\nexport function inferUiType(field: ParsedField, opts: InferenceOptions = {}): FieldType {\n\tif (field.ui.type) return field.ui.type as FieldType;\n\n\tif (Array.isArray(field.choices) && field.choices.length > 0) return 'enum';\n\tif (field.foreignKey) return 'reference';\n\n\tconst nameLower = field.name.toLowerCase();\n\tif (nameLower.includes('email')) return 'email';\n\tif (nameLower.includes('url') || nameLower.includes('website')) return 'url';\n\tif (nameLower.includes('password')) return 'password';\n\tif (\n\t\tnameLower.includes('price') ||\n\t\tnameLower.includes('amount') ||\n\t\tnameLower.includes('cost') ||\n\t\tnameLower.includes('value') ||\n\t\tnameLower.includes('revenue')\n\t) {\n\t\treturn 'money';\n\t}\n\tif (nameLower.includes('percent') || nameLower.includes('rate')) {\n\t\treturn 'percentage';\n\t}\n\n\tconst threshold =\n\t\topts.textareaThreshold === undefined ? DEFAULT_TEXTAREA_THRESHOLD : opts.textareaThreshold;\n\n\tswitch (field.type) {\n\t\tcase 'string':\n\t\t\treturn threshold !== null &&\n\t\t\t\tfield.constraints.maxLength &&\n\t\t\t\tfield.constraints.maxLength > threshold\n\t\t\t\t? 'textarea'\n\t\t\t\t: 'text';\n\t\tcase 'integer':\n\t\tcase 'decimal':\n\t\t\treturn 'number';\n\t\tcase 'boolean':\n\t\t\treturn 'boolean';\n\t\tcase 'uuid':\n\t\t\treturn 'text';\n\t\tcase 'date':\n\t\t\treturn 'date';\n\t\tcase 'datetime':\n\t\t\treturn 'datetime';\n\t\tcase 'json':\n\t\t\treturn 'json';\n\t\tdefault:\n\t\t\treturn 'text';\n\t}\n}\n\n/**\n * Infer UI importance. Explicit `ui.importance` wins; then id/timestamps →\n * tertiary, FK `*_id` → secondary, required → primary, name/title → primary,\n * else secondary. Ported from prompt.js `inferUiImportance`.\n */\nexport function inferUiImportance(field: ParsedField): FieldImportance {\n\tif (field.ui.importance) return field.ui.importance as FieldImportance;\n\n\tconst nameLower = field.name.toLowerCase();\n\tif (['id', 'created_at', 'updated_at', 'deleted_at'].includes(nameLower)) {\n\t\treturn 'tertiary';\n\t}\n\tif (field.foreignKey && nameLower.endsWith('_id')) return 'secondary';\n\tif (field.required) return 'primary';\n\tif (nameLower.includes('name') || nameLower.includes('title')) return 'primary';\n\treturn 'secondary';\n}\n\n/**\n * Whether a field is internal entity_ref machinery the metadata display skips\n * (the `isEntityRefType`/`isEntityRefId` skip in the old `fields.ejs.t`). The\n * parser emits these as `entity_ref` typed fields; in the generated DB the pair\n * surfaces as `<base>_entity_type` / `<base>_entity_id`. We skip both the base\n * `entity_ref` field and the derived `_entity_type` / `_entity_id` columns.\n */\nexport function isEntityRefField(field: ParsedField): boolean {\n\tif (field.type === 'entity_ref') return true;\n\treturn field.name.endsWith('_entity_type') || field.name.endsWith('_entity_id');\n}\n\n/**\n * Derive the full UI metadata for one field. The `id` field is filtered by the\n * caller (the template skipped it); this returns metadata for any non-skipped\n * field. `reference` is the FK target table (the registry resolves display\n * names elsewhere). `choices` carries explicit enum choices.\n *\n * Authored `ui_*` hints pass through verbatim: `group` / `visible` /\n * `placeholder` / `help` / `format`. `defaults` fills entity-level derivation\n * defaults (currently `group`) only where the author left the hint unset.\n * `keyFieldOrder` is emitted only alongside `isKeyField: true` — an order\n * without curation is meaningless.\n *\n * `opts` is forwarded to {@link inferUiType} — pass `{ textareaThreshold }`\n * from `frontend.fields.textareaThreshold` to honour the project config.\n */\nexport function deriveFieldMeta(\n\tfield: ParsedField,\n\tdefaults: FieldMetaDefaults = {},\n\topts: InferenceOptions = {},\n): DerivedFieldMeta {\n\tconst hasChoices = Array.isArray(field.choices) && field.choices.length > 0;\n\tconst meta: DerivedFieldMeta = {\n\t\tfield: CAMEL(field.name),\n\t\tlabel: field.ui.label ?? formatLabel(field.name),\n\t\ttype: inferUiType(field, opts),\n\t\timportance: inferUiImportance(field),\n\t\tsortable: field.ui.sortable ?? false,\n\t\tfilterable: field.ui.filterable ?? false,\n\t};\n\tconst group = field.ui.group ?? defaults.group;\n\tif (group !== undefined) meta.group = group;\n\tif (field.ui.visible !== undefined) meta.visible = field.ui.visible;\n\tif (field.ui.placeholder !== undefined) meta.placeholder = field.ui.placeholder;\n\tif (field.ui.help !== undefined) meta.help = field.ui.help;\n\tif (field.ui.format !== undefined) meta.format = field.ui.format;\n\tif (hasChoices) meta.choices = field.choices;\n\tif (field.foreignKey) meta.reference = field.foreignKey.table;\n\tif (field.ui.keyField) {\n\t\tmeta.isKeyField = true;\n\t\tif (field.ui.keyFieldOrder !== undefined) {\n\t\t\tmeta.keyFieldOrder = field.ui.keyFieldOrder;\n\t\t}\n\t}\n\treturn meta;\n}\n\n// ============================================================================\n// External-sync shape (family/behavior bundle, ADR-040)\n// ============================================================================\n\n/** Default `group` applied to external-sync bookkeeping fields. */\nexport const EXTERNAL_SYNC_GROUP = 'external_sync';\n\n/**\n * The field names that make up the synced/integrated bookkeeping shape — the\n * columns the `external_id_tracking` behavior contributes when authors declare\n * them explicitly in YAML instead. `provider_metadata` rides along: it only\n * receives the default when the gate below detects the shape.\n */\nexport const EXTERNAL_SYNC_FIELDS: ReadonlySet<string> = new Set([\n\t'external_id',\n\t'provider',\n\t'provider_metadata',\n]);\n\n/**\n * Whether an entity's declared fields carry the synced/integrated shape:\n * BOTH `external_id` AND `provider` present. When true, the fields emitter\n * defaults `group: 'external_sync'` onto the `EXTERNAL_SYNC_FIELDS` rows\n * (a derivation default — an authored `ui_group` always wins).\n *\n * Conservative by design: this inspects only fields that exist in the parsed\n * map. Columns contributed by the `external_id_tracking` BEHAVIOR are not in\n * the parsed field map and therefore get no FieldMeta rows at all (same as\n * before ADR-040) — we never emit a row for a column we cannot see.\n */\nexport function hasExternalSyncShape(fieldNames: Iterable<string>): boolean {\n\tconst names = new Set(fieldNames);\n\treturn names.has('external_id') && names.has('provider');\n}\n\n// ============================================================================\n// EAV data_type → FieldType contract (ADR-040)\n// ============================================================================\n\n/**\n * The EAV `field_definitions.data_type` vocabulary → frontend `FieldType`\n * rendering contract. This is the rallying point for external-system field\n * types: an EAV row's `data_type` maps through this table to the same\n * rendering vocabulary native columns use, so one renderer serves both.\n *\n * Notes:\n * - `picklist` AND `multipicklist` both map to `enum` — multi-select rendering\n * is a consumer-side concern (the renderer checks the EAV row's cardinality,\n * not the FieldType).\n * - `string` maps to `text`; EAV has no textarea heuristic (no `max_length`).\n *\n * The same constant is emitted into the generated `fields/field-meta.ts` (see\n * `buildFieldMetaTypeFile`) so consumer apps get it locally, rendered from\n * THIS object — the two cannot drift.\n */\nexport const EAV_DATA_TYPE_TO_FIELD_TYPE = {\n\tstring: 'text',\n\tinteger: 'number',\n\tdecimal: 'number',\n\tboolean: 'boolean',\n\tdate: 'date',\n\tdatetime: 'datetime',\n\tjson: 'json',\n\treference: 'reference',\n\tpicklist: 'enum',\n\tmultipicklist: 'enum',\n} as const satisfies Record<string, FieldType>;\n\n/** The EAV `field_definitions.data_type` vocabulary. */\nexport type EavDataType = keyof typeof EAV_DATA_TYPE_TO_FIELD_TYPE;\n","/**\n * Entity Codegen & Domain Analyzer\n *\n * A validation and analysis tool for entity YAML definitions.\n * Parses entities, builds a relationship graph, and detects issues.\n */\n\nimport { loadEntities, loadRelationships, resolveReferences, resolveRelationshipReferences } from './parser';\nimport { buildDomainGraph, checkConsistency, computeStatistics } from './analyzer';\nimport {\n\tvalidatePatternComposition,\n\tvalidatePatternProject,\n} from './patterns/validate-composition.js';\nimport { validateOrchestrationProject } from './patterns/validate-orchestration.js';\nimport {\n\tgetAllOrchestrationPatterns,\n\tgetAllPatternNames,\n} from './patterns/registry.js';\nimport type { AnalysisResult, OutputFormat } from './analyzer/types';\n\n/**\n * Options for `analyzeDomain`. All fields are optional and additive — omitting\n * them keeps the analyzer's behavior identical to pre-PATTERN-4 callers.\n */\nexport interface AnalyzeDomainOptions {\n\t/**\n\t * Path to the relationships directory. Equivalent to the legacy second\n\t * positional argument — preserved for call-site compatibility.\n\t */\n\trelationshipsDir?: string;\n\t/**\n\t * Selected backend architecture from `codegen.config.yaml\n\t * generate.architecture`. When provided, enables the PATTERN-4 project-level\n\t * check (plan Risk 4) that warns when `pattern:` is declared but the\n\t * selected architecture does not yet consume patterns (e.g. `clean`).\n\t */\n\tarchitecture?: string;\n}\n\n/**\n * Analyze a domain from entity and relationship YAML files.\n *\n * The signature accepts either the legacy `(entitiesDir, relationshipsDir)`\n * shape or the newer `(entitiesDir, options)` object form. Existing callers\n * keep working unchanged; pattern-aware callers pass\n * `{ architecture, relationshipsDir }` to opt into the Risk-4 project-level\n * warning surface.\n */\nexport async function analyzeDomain(\n\tentitiesDir: string,\n\trelationshipsOrOptions?: string | AnalyzeDomainOptions,\n): Promise<AnalysisResult> {\n\tconst opts: AnalyzeDomainOptions =\n\t\ttypeof relationshipsOrOptions === 'string'\n\t\t\t? { relationshipsDir: relationshipsOrOptions }\n\t\t\t: relationshipsOrOptions ?? {};\n\tconst relationshipsDir = opts.relationshipsDir;\n\n\t// Load and parse all entity files\n\tconst { entities, issues: loadIssues } = loadEntities(entitiesDir);\n\n\t// Load relationship definitions (optional — directory may not exist)\n\tconst { relationships: relationshipDefinitions, issues: relLoadIssues } =\n\t\trelationshipsDir\n\t\t\t? loadRelationships(relationshipsDir)\n\t\t\t: { relationships: [], issues: [] };\n\n\t// Resolve cross-entity references\n\tconst resolveIssues = resolveReferences(entities);\n\n\t// Resolve relationship endpoint references\n\tconst relResolveIssues = resolveRelationshipReferences(\n\t\trelationshipDefinitions,\n\t\tentities,\n\t);\n\n\t// Build relationship graph (includes both inline and first-class relationships)\n\tconst graph = buildDomainGraph(entities, relationshipDefinitions);\n\n\t// Check consistency\n\tconst consistencyIssues = checkConsistency(graph);\n\n\t// PATTERN-4 — pattern composition check. Runs AFTER resolveReferences()\n\t// (per ADR-031 §3) so entity fields + behaviors are known; the\n\t// per-entity validator detects column conflicts, unknown patterns, and\n\t// config-schema failures, and the project-level validator covers plan\n\t// Risk 4 (warn when `pattern:` is declared under an architecture that\n\t// does not yet consume patterns).\n\tconst patternIssues = entities.flatMap((e) => validatePatternComposition(e));\n\tconst patternProjectIssues = validatePatternProject({\n\t\tentities,\n\t\tarchitecture: opts.architecture,\n\t});\n\n\t// ADR-032 Phase 3-1 — orchestration pattern project-level validator.\n\t// Compares orchestration names against the domain name set (cross-kind\n\t// collision is a hard error), and walks each orchestration pattern's\n\t// registry shape for malformed entries, duplicate keys, and co-keyed\n\t// keyType drift.\n\tconst orchestrationProjectIssues = validateOrchestrationProject({\n\t\torchestrationPatterns: getAllOrchestrationPatterns(),\n\t\tdomainPatternNames: getAllPatternNames(),\n\t});\n\n\t// Compute statistics\n\tconst statistics = computeStatistics(graph);\n\n\t// Combine all issues\n\tconst allIssues = [\n\t\t...loadIssues,\n\t\t...relLoadIssues,\n\t\t...resolveIssues,\n\t\t...relResolveIssues,\n\t\t...consistencyIssues,\n\t\t...patternIssues,\n\t\t...patternProjectIssues,\n\t\t...orchestrationProjectIssues,\n\t];\n\n\t// Determine validity (only errors make it invalid)\n\tconst hasErrors = allIssues.some((i) => i.severity === 'error');\n\n\treturn {\n\t\tisValid: !hasErrors,\n\t\tentities,\n\t\trelationshipDefinitions,\n\t\tgraph,\n\t\tissues: allIssues,\n\t\tstatistics,\n\t};\n}\n\n/**\n * Validate entity files without full analysis\n * Returns true if all files parse successfully\n */\nexport function validateEntities(entitiesDir: string): {\n\tvalid: boolean;\n\terrors: string[];\n} {\n\tconst { entities, issues } = loadEntities(entitiesDir);\n\tconst errors = issues\n\t\t.filter((i) => i.severity === 'error')\n\t\t.map((i) => i.message);\n\n\treturn {\n\t\tvalid: errors.length === 0,\n\t\terrors,\n\t};\n}\n\n// Re-export types\nexport * from './analyzer/types';\n\n// Re-export parser utilities\nexport { loadEntities, loadRelationships, loadEntityFromYaml, loadRelationshipFromYaml, loadJunctionFromYaml } from './parser';\n\n// Re-export junction definition schema surface\nexport {\n\tJunctionDefinitionSchema,\n\tvalidateJunctionDefinition,\n\tsafeValidateJunctionDefinition,\n\ttype JunctionDefinition,\n} from './schema/junction-definition.schema';\n\n// Re-export analyzer utilities\nexport {\n\tbuildDomainGraph,\n\tgetRelatedEntities,\n\tfindOrphanEntities,\n\tfindCircularDependencies,\n\tcheckConsistency,\n\tcomputeStatistics,\n} from './analyzer';\n\n// Re-export formatters\nexport {\n\tformatConsole,\n\tformatJson,\n\tformatMarkdown,\n\tformatMermaidGraph,\n} from './formatters';\n\n\n// Re-export patterns surface (definePattern + library patterns + registry).\n// Importing this barrel has the side effect of pre-registering the five\n// library-shipped patterns (Base / Integrated / Activity / Knowledge / Metadata).\nexport * from './patterns';\n\n// Re-export the field-metadata vocabulary contract (ADR-040): the EAV\n// `field_definitions.data_type` → frontend `FieldType` mapping. The same\n// constant is emitted into generated apps' `fields/field-meta.ts`; this export\n// serves tooling that consumes `@pattern-stack/codegen` directly.\nexport {\n\tEAV_DATA_TYPE_TO_FIELD_TYPE,\n\ttype EavDataType,\n} from './emitters/frontend/field-meta';\n"],"mappings":"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","names":["resolve","z","z","z","z","z","z","SNAKE_CASE_RE","z","EventTriggerSchema","path","resolve","resolve","loadErrorToIssue","resolve","existsSync","readFileSync","join","resolve","path","readFileSync","join","resolve","existsSync","resolve","path","path","readFileSync","existsSync","readdirSync","statSync","join","join","existsSync","readdirSync","statSync","readFileSync","z","z","z","z"]}