@happyvertical/smrt-core 0.57.15 → 0.57.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/manifest/static-manifest.js +1 -1
- package/dist/manifest/static-manifest.js.map +1 -1
- package/dist/manifest/store.js +1 -1
- package/dist/manifest.json +1 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +30 -9
- package/dist/registry.js.map +1 -1
- package/dist/scanner/manifest-generator.d.ts +9 -0
- package/dist/scanner/manifest-generator.d.ts.map +1 -1
- package/dist/scanner/manifest-generator.js +41 -24
- package/dist/scanner/manifest-generator.js.map +1 -1
- package/dist/smrt-knowledge.json +4 -4
- package/dist/vite-plugin/sveltekit-generator.d.ts.map +1 -1
- package/dist/vite-plugin/sveltekit-generator.js +2 -0
- package/dist/vite-plugin/sveltekit-generator.js.map +1 -1
- package/package.json +5 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest-generator.js","names":[],"sources":["../../src/scanner/manifest-generator.ts"],"sourcesContent":["/**\n * Manifest generator for creating service manifests from AST scan results\n */\n\nimport { createHash } from 'node:crypto';\nimport { createRequire } from 'node:module';\nimport { createLogger } from '@happyvertical/logger';\nimport { ConfigurationError } from '../errors.js';\nimport {\n createManifestClassNamePredicate,\n resolveApiMethodExposure,\n resolveCustomActionMetadata,\n resolveEffectiveActionMetadata,\n} from '../generators/custom-action.js';\nimport {\n loadExternalManifestSync,\n lookupInManifest,\n} from '../manifest/manifest-loader.js';\nimport { findField, type HelpModel, validateHelp } from '../recipe-help.js';\nimport {\n findCollectionWriteEscalations,\n formatCollectionWriteEscalations,\n inheritCollectionExposure,\n} from '../registry/collection-exposure.js';\nimport { isSmrtCollectionExtendsName } from '../registry/collection-resolution.js';\nimport { VERBOSE_ENABLED } from '../registry/shared-state.js';\nimport {\n findStaleWidenings,\n findSubclassExposureEscalations,\n formatSubclassExposureEscalations,\n inheritSubclassExposure,\n} from '../registry/subclass-exposure.js';\nimport type { SmartObjectConfig } from '../registry/types.js';\nimport {\n defaultConflictColumns,\n resolveOwnershipTenantColumn,\n resolveTenantColumn,\n} from '../schema/conflict-target.js';\nimport type { DatabaseEngine } from '../schema/ddl/types.js';\nimport {\n resolveForeignKeyDeleteAction,\n resolveForeignKeyUpdateAction,\n} from '../schema/foreign-key-policy.js';\nimport { SchemaGenerator } from '../schema/generator.js';\nimport type {\n ColumnDefinition,\n SchemaDefinition,\n SQLDataType,\n} from '../schema/types.js';\nimport { generateToolManifest } from '../tools/tool-generator.js';\nimport {\n displayLabelFieldProblem,\n FIELD_UI_FORMAT_TYPES,\n FIELD_UI_FORMATS,\n FIELD_UI_WIDGET_TYPES,\n FIELD_UI_WIDGETS,\n isFieldUIFormat,\n isFieldUIWidget,\n isRelationshipRole,\n RELATIONSHIP_ROLES,\n resolveDisplayLabelField,\n} from '../ui-metadata.js';\nimport { classnameToTablename, toSnakeCase } from '../utils/naming.js';\nimport {\n assertScopedPackageName,\n createQualifiedName,\n isQualifiedName,\n isQualifiedNameAliasFormat,\n parseQualifiedName,\n readPreviousQualifiedNames,\n} from '../utils/qualified-names.js';\nimport { applyRecipeDemo } from './recipe-demo-pass.js';\nimport { isTestFile } from './test-file-patterns.js';\nimport type {\n AgentAdminRouteManifest,\n AgentComponentDeclaration,\n AgentCreateEntryManifest,\n AgentFeature,\n AgentManifest,\n AgentMenuItem,\n AgentPermission,\n AgentUISlotManifest,\n FieldDefinition,\n ManifestColumnDefinition,\n ManifestSchema,\n MethodDefinition,\n ScanResult,\n SmartObjectDefinition,\n SmartObjectManifest,\n SmrtVisibility,\n ValidationRule,\n} from './types.js';\nimport { MANIFEST_TIMESTAMP } from './types.js';\n\n/** Package.json shape consumed for import-path and component discovery. */\ninterface PackageJsonLike {\n name?: string;\n main?: string;\n exports?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\n/**\n * Object form of the `@smrt({ tenantScoped })` config. Mirrors the object\n * branch of `SmartObjectConfig['tenantScoped']`; all keys optional because\n * the boolean shorthand normalizes to `{}`.\n */\ninterface TenantScopedOptions {\n mode?: 'required' | 'optional';\n field?: string;\n autoFilter?: boolean;\n autoPopulate?: boolean;\n allowSuperAdminBypass?: boolean;\n}\n\n/** JSON Schema property entry emitted for a field in generated MCP tools. */\ninterface JsonSchemaProperty {\n type: string;\n description: string;\n minimum?: number;\n maximum?: number;\n minLength?: number;\n maxLength?: number;\n enum?: Array<string | number>;\n}\n\ntype SchemaGeneratorLike = {\n generateSQL: (schema: SchemaDefinition, engine?: DatabaseEngine) => string;\n};\n\n// Create require function for synchronous module loading in ESM context\nconst require = createRequire(import.meta.url);\n\n// Build-time schema/manifest-generation diagnostics route through the shared\n// logger (S14 / dim-9, #1579) instead of unconditional stdout writes. Level\n// follows the repo-wide SMRT_VERBOSE/DEBUG convention (#2896) so per-class\n// detail is opt-in rather than always-on info.\nconst logger = createLogger({ level: VERBOSE_ENABLED ? 'debug' : 'info' });\n\n/**\n * Fields every `SmrtObject` carries that are not manifest fields (#3590): a\n * recipe option may still refine them.\n */\nconst UNIVERSAL_OBJECT_FIELDS = [\n 'id',\n 'slug',\n 'context',\n 'created_at',\n 'updated_at',\n];\n\n/**\n * Framework abstract base classes whose declared fields must be merged\n * into every subclass's `fields` map.\n *\n * These classes live in SMRT framework packages, have no `@smrt()`\n * decorator, no table of their own, and contribute structural fields\n * (e.g. `SmrtHierarchical.parentId`) that subclasses query against —\n * without merging, downstream WHERE-clause validation rejects queries on\n * those columns.\n *\n * SmrtObject / SmrtClass / SmrtCollection are intentionally NOT in this\n * set even though they live in core. SmrtObject's universal columns\n * (`id`, `slug`, `context`, `created_at`, `updated_at`) are added by a\n * separate universal-baseline mechanism in `fieldsFromClass`, and merging\n * them here would double-write with subtly different `_meta` payloads\n * and regress existing field expectations.\n *\n * Keep in sync with `FRAMEWORK_BASE_CLASSES` in\n * `packages/scanner/src/inheritance-resolver.ts` — note that set is\n * broader: it controls scanner-level chain termination and stub\n * resolution, while this one only controls field merging.\n */\nconst FRAMEWORK_ABSTRACT_BASE_NAMES = new Set([\n 'SmrtJunction',\n 'SmrtJunctionBase',\n 'SmrtHierarchical',\n 'SmrtPolymorphicAssociation',\n 'SmrtReport',\n 'SmrtReportCollection',\n]);\n\n/**\n * Framework base classes to exclude from the ancestor **method** merge\n * below (#2624). Unlike fields, methods are never columns, so they never\n * needed the STI-vs-CTI field-merge rule above — they inherited it only by\n * sharing the same loop.\n *\n * Deliberately NARROWER than `FRAMEWORK_ABSTRACT_BASE_NAMES`: only the\n * three universal object/collection primitives (`SmrtObject`, `SmrtClass`,\n * `SmrtCollection`) are internal-only. These are the same three the\n * runtime resolver's `getAllMethods()`\n * (`packages/core/src/registry/inheritance-resolver.ts`) explicitly skips\n * by name, and the same three the field-merge doc comment above excludes\n * from `FRAMEWORK_ABSTRACT_BASE_NAMES` for the identical reason: their\n * surface (`save`, `destroy`, `toJSON`, `withTransaction`, ...) is generic\n * object-lifecycle plumbing, never a subclass-specific action.\n *\n * `FRAMEWORK_ABSTRACT_BASE_NAMES` (`SmrtJunction`, `SmrtHierarchical`,\n * `SmrtPolymorphicAssociation`, `SmrtReport`, `SmrtReportCollection`) is\n * intentionally NOT folded in here, unlike an earlier version of this fix.\n * Those classes are mixin-style bases whose declared methods ARE the\n * subclass's real, intended public API — the same way `SmrtHierarchical.\n * parentId` is a real, intended field, which is exactly why\n * `FRAMEWORK_ABSTRACT_BASE_NAMES` fields already merge into every subclass\n * regardless of STI/CTI (see above). Directly confirmed for two of the\n * five: `SmrtJunction.attach`/`detach`/`byLeft`/`byRight`/`setLinks`\n * (`packages/core/src/junction.ts`) — a `packages/template-sveltekit/\n * __tests__/runtimeProfileParity.test.ts` snapshot broke when an earlier\n * revision of this fix folded all 8 `FRAMEWORK_BASE_CLASSES` in here,\n * which is how this got caught — and `SmrtHierarchical.getParent`/\n * `getChildren`/`getAncestors`/`getDescendants`/`getHierarchy`/`moveTo`\n * (`packages/core/src/hierarchical.ts`). `SmrtPolymorphicAssociation`\n * follows the identical pattern by inspection but has no dedicated\n * regression test yet. `SmrtReport`/`SmrtReportCollection` are the\n * least-audited of the five: `SmrtReportCollection` overrides `list`/`get`\n * (`packages/reports/src/report.ts`), which are also the universal CRUD\n * operation names — a downstream `class X extends SmrtReportCollection`\n * with default (non-strict) MCP config would have seen a generated\n * custom-action tool collide with the standard `list`/`get` tool name.\n * #2646 closed that separately and independently of this exclusion set: the\n * MCP generator now refuses to expose a CRUD-named method as a custom action,\n * matching case-folded because its tool ids are lowercased whole. Each emitter\n * reserves on its own terms, and not all of them read the shared\n * `CRUD_OPERATIONS` list yet — see its docblock in\n * `generators/custom-action.ts` for the per-emitter rules. Keep in sync with the field-merge set's own doc comment; this one\n * governs method merging only.\n */\nconst FRAMEWORK_METHOD_BASE_NAMES = new Set([\n 'SmrtObject',\n 'SmrtClass',\n 'SmrtCollection',\n]);\n\n/**\n * Deterministic string comparator (#2749). Manifest object iteration order\n * follows scan/discovery order, which is not stable across runs, so any\n * emitted artifact keyed off `Object.entries(manifest.objects)` needs a\n * stable sort before emission.\n */\nfunction compareText(left: string, right: string): number {\n if (left < right) return -1;\n if (left > right) return 1;\n return 0;\n}\n\n/**\n * True when a package.json `exports` condition resolves to a non-JS asset\n * (e.g. the `./manifest`/`./manifest.json` convention pointing at\n * `dist/manifest.json`), so subpath matching (smrt#2845's\n * `matchExportsSubpath`) never attributes a scanned object to it — no\n * `@smrt()` class's source file can be loaded from a JSON target.\n */\nfunction targetsJsonAsset(condition: unknown): boolean {\n if (typeof condition === 'string') return condition.endsWith('.json');\n if (condition && typeof condition === 'object') {\n const record = condition as Record<string, unknown>;\n const target = record.import ?? record.default ?? record.require;\n return typeof target === 'string' && target.endsWith('.json');\n }\n return false;\n}\n\n/**\n * Infer visibility from file path and explicit config\n *\n * Priority:\n * 1. Explicit visibility in decorator config\n * 2. Auto-detect test files → 'test'\n * 3. Default to 'public'\n */\nfunction inferVisibility(\n filePath: string,\n explicitVisibility?: SmrtVisibility,\n): SmrtVisibility {\n if (explicitVisibility) return explicitVisibility;\n if (isTestFile(filePath)) return 'test';\n return 'public';\n}\n\nexport class ManifestGenerator {\n /**\n * Generate manifest from scan results\n *\n * @param scanResults - Array of scan results containing object definitions\n * @param options - Optional configuration\n * @param options.packageName - Package name to inject into manifest and object definitions\n * @param options.packageVersion - Package version\n * @param options.packageJson - Full package.json object for determining import paths\n * @param options.smrtDependencies - List of SMRT package dependencies to include in manifest\n * @param options.includeVisibility - Array of visibility levels to include (default: all)\n * - For published packages: ['public']\n * - For development: ['public', 'internal', 'test'] or omit for all\n */\n generateManifest(\n scanResults: ScanResult[],\n options?: {\n packageName?: string;\n packageVersion?: string;\n packageJson?: PackageJsonLike;\n smrtDependencies?: string[];\n includeVisibility?: SmrtVisibility[];\n },\n ): SmartObjectManifest {\n const manifest: SmartObjectManifest = {\n version: '1.0.0',\n timestamp: MANIFEST_TIMESTAMP,\n objects: {},\n };\n\n if (scanResults.some((result) => result.objects.length > 0)) {\n assertScopedPackageName(options?.packageName);\n }\n\n // Set package metadata at manifest level if provided\n if (options?.packageName) {\n manifest.packageName = options.packageName;\n }\n if (options?.packageVersion) {\n manifest.packageVersion = options.packageVersion;\n }\n // Set smrtDependencies BEFORE mergeInheritedFields() so external packages can be loaded\n if (options?.smrtDependencies) {\n manifest.smrtDependencies = options.smrtDependencies;\n }\n\n for (const result of scanResults) {\n for (const objectDef of result.objects) {\n // Set package metadata on object definition if provided\n if (options?.packageName) {\n objectDef.packageName = options.packageName;\n }\n if (options?.packageVersion) {\n objectDef.packageVersion = options.packageVersion;\n }\n\n // Generate qualified name (required for manifest keying)\n // Must have packageName to generate qualified name\n if (objectDef.packageName) {\n objectDef.qualifiedName = createQualifiedName(\n objectDef.packageName,\n objectDef.className,\n );\n }\n\n // Infer visibility from file path and decorator config\n objectDef.visibility = inferVisibility(\n objectDef.filePath,\n objectDef.decoratorConfig?.visibility as SmrtVisibility | undefined,\n );\n\n // Filter by visibility if specified\n // Skip objects that don't match the requested visibility levels\n if (\n options?.includeVisibility &&\n options.includeVisibility.length > 0 &&\n !options.includeVisibility.includes(objectDef.visibility)\n ) {\n // Skip this object - visibility not in allowed list\n continue;\n }\n\n // Determine import path from package.json exports\n if (options?.packageName && options?.packageJson) {\n objectDef.importPath = this.determineImportPath(\n options.packageJson,\n objectDef.filePath,\n );\n }\n\n // Set export names (defaults to className)\n objectDef.exportName = objectDef.exportName || objectDef.className;\n objectDef.collectionExportName =\n objectDef.collectionExportName || `${objectDef.className}Collection`;\n\n // Generate AI tools from methods if AI config exists\n if (objectDef.decoratorConfig.ai) {\n const methods = Object.values(objectDef.methods);\n const tools = generateToolManifest(\n methods,\n objectDef.decoratorConfig.ai,\n );\n\n // Store tools in object definition\n if (tools.length > 0) {\n objectDef.tools = tools;\n }\n }\n\n // Determine manifest key: use qualified name if available, fall back to lowercase name\n // During transition, some objects may not have qualified names\n const manifestKey = objectDef.qualifiedName || objectDef.name;\n\n // Check for collisions using the manifest key\n if (manifest.objects[manifestKey]) {\n const existing = manifest.objects[manifestKey];\n throw new Error(\n `Class name collision detected: '${objectDef.className}' (${manifestKey}) is defined in multiple files:\\n` +\n ` 1. ${existing.filePath}\\n` +\n ` 2. ${objectDef.filePath}\\n\\n` +\n `Class names must be unique within a package. Use different class names or separate packages.`,\n );\n }\n\n manifest.objects[manifestKey] = objectDef;\n }\n }\n\n this.applyGenerationPasses(manifest, {\n packageName: options?.packageName,\n packageJson: options?.packageJson,\n });\n\n return manifest;\n }\n\n /**\n * Run every manifest generation pass, in order, on a manifest whose\n * `objects` have been collected. This is THE pass sequence: the OXC vite\n * plugin (`vite-plugin/index.ts`) and `ManifestBuilder.buildManifest()`\n * call it too, so the three producers cannot drift — before #2360\n * `ManifestBuilder` skipped the report passes and its manifests carried\n * `(slug, context)` conflict indexes for `@report` classes while the\n * runtime upserted on the report's group columns.\n *\n * @param manifest - manifest with `objects` populated (and\n * `smrtDependencies` set, so external STI bases resolve)\n * @param options - package metadata for the agent-manifest pass\n */\n applyGenerationPasses(\n manifest: SmartObjectManifest,\n options?: { packageName?: string; packageJson?: PackageJsonLike },\n ): void {\n // An unscoped package name would yield `pkg:Class` keys the registry\n // rejects at startup (#3408); fail here with an actionable message. An app\n // that declares no classes generates no qualified names and still builds.\n if (Object.keys(manifest.objects).length > 0) {\n assertScopedPackageName(options?.packageName);\n }\n\n // Capture authored API exposure before making the abstract class itself\n // read-only so hosted concrete descendants can inherit the authored part.\n for (const objectDef of Object.values(manifest.objects)) {\n if (objectDef.decoratorConfig?.abstract !== true) continue;\n if (!Object.hasOwn(objectDef, 'abstractDeclaredApi')) {\n objectDef.abstractDeclaredApi = objectDef.decoratorConfig.api ?? null;\n }\n }\n\n // Deprecated qualified-name aliases (#3338) fail closed at build time, the\n // same as the registry refuses them at runtime.\n this.assertQualifiedNameAliases(manifest);\n\n // Keep only import-derived parent qualifications the parent's package\n // confirms (#4145), before any pass walks `extendsQualified`.\n this.verifyImportedParents(manifest);\n\n // Report cache rows are safe to scope by tenant even when a report is\n // global: optional mode keeps tenant-less rows readable outside a tenant\n // context and gives tenant-scoped reports the tenant_id column their raw\n // aggregate refresh path must write.\n this.normalizeReportTenantScope(manifest);\n\n // Second pass: materialize implicit tenant fields before inheritance and schema generation.\n this.injectTenantScopedFields(manifest);\n\n // Report models default to a read-only surface. Apply that before\n // inheritance, so a report model's collection inherits it and the\n // collection-exposure guard sees it.\n this.applyReportSurfaceDefaults(manifest);\n\n // Third pass: Merge inherited fields for STI classes\n // This ensures STI subclasses have all parent fields inline in the manifest\n this.mergeInheritedFields(manifest);\n\n // A model subclass may narrow its parent's generated surface but not\n // widen it. Before the abstract pass below, which synthesizes write\n // exclusions on an abstract parent that its concrete subclasses exist to\n // lift.\n this.assertSubclassExposure(manifest);\n\n // All producers, including OXC, must suppress custom actions on abstract\n // resources and their collection classes. Do this after inheritance so\n // ancestor methods are covered and projections share the same exclusions.\n const objectsByName = new Map(\n Object.values(manifest.objects).map((objectDef) => [\n objectDef.className,\n objectDef,\n ]),\n );\n for (const objectDef of Object.values(manifest.objects)) {\n const config = objectDef.decoratorConfig;\n const isCollection =\n objectDef.extends === 'SmrtCollection' ||\n this.extendsCollection(objectDef, objectsByName);\n let collectionItem: SmartObjectDefinition | undefined;\n if (isCollection) {\n const seenParents = new Set<string>();\n let candidate: SmartObjectDefinition | undefined = objectDef;\n while (candidate) {\n if (candidate.extendsTypeArg || candidate.fields._itemClass) {\n collectionItem = this.findItemClass(\n candidate,\n manifest,\n objectsByName,\n );\n break;\n }\n const parentName = candidate.extendsQualified || candidate.extends;\n if (!parentName || seenParents.has(parentName)) break;\n seenParents.add(parentName);\n candidate = lookupInManifest(manifest, parentName) as\n | SmartObjectDefinition\n | undefined;\n }\n collectionItem ??= this.findItemClass(\n objectDef,\n manifest,\n objectsByName,\n );\n }\n const itemIsAbstract = collectionItem?.decoratorConfig?.abstract === true;\n if (config?.abstract !== true && !itemIsAbstract) continue;\n const methods = Object.entries(objectDef.methods || {})\n .filter(([, method]) => method.isPublic)\n .map(([name]) => name)\n .filter((name) => name !== 'list' && name !== 'get');\n for (const surface of ['api', 'mcp', 'cli'] as const) {\n if (config[surface] === false) continue;\n const current = config[surface];\n const excludes =\n current && typeof current === 'object' && current.exclude\n ? current.exclude\n : [];\n config[surface] = {\n ...(current && typeof current === 'object' ? current : {}),\n exclude: [\n ...new Set([...excludes, 'create', 'update', 'delete', ...methods]),\n ],\n };\n }\n }\n\n // A collection may not open a generated write its model closes. After\n // the abstract pass above, which closes writes over abstract models.\n this.assertCollectionExposure(manifest);\n\n // Recipe options may only name fields the merged model declares (#3590).\n this.assertRecipeOptions(manifest);\n this.assertRecipeHelp(manifest);\n // Browser capability of the package and the demo mode of its recipes (#3709).\n applyRecipeDemo(manifest, options?.packageName);\n\n // Presentation metadata (#3599): widget hints, display label, selector\n // bindings. After inheritance so a label may name an inherited STI column.\n this.applyUiMetadata(manifest);\n\n // Report models are read-only cache tables. Fill in the generated surface\n // and natural conflict key from report metadata before schema generation.\n this.normalizeReportObjects(manifest);\n\n // Tenant-scoped classes key on `[tenant column, ...natural key]` (#2360);\n // materialize that default so schema generation, the knowledge artifact\n // and the runtime read the same conflict target.\n this.normalizeConflictColumns(manifest);\n\n // Fourth pass: Generate validation rules for all objects\n // This pre-computes validation rules from field definitions, eliminating\n // the need to compile validator closures at runtime (Issue #782)\n this.generateValidationRules(manifest);\n\n // Fifth pass: Generate schemas for each object (build-time schema generation)\n // This pre-computes DDL, indexes, and columns for efficient external package consumption\n this.generateSchemas(manifest);\n this.assertTenantScopedSchemaContract(manifest);\n\n // Sixth pass: Generate agent manifests for Agent subclasses\n // Derives permissions, features, menuItems, and components from code\n this.generateAgentManifests(\n manifest,\n options?.packageName,\n options?.packageJson,\n );\n\n // Seventh pass: stamp the subpath consumers should import each object\n // from. `generateManifest()`'s own per-object loop already does this,\n // but the Vite plugin and `ManifestBuilder` (the other two manifest\n // producers this pass sequence exists to keep from drifting, #2360)\n // build their manifest via `ManifestAdapter.toManifest()` and call\n // `applyGenerationPasses()` directly — never through `generateManifest()`\n // — so their objects reached this pass with no `importPath` at all. That\n // is smrt#2845: `DataSurfaceActionIdempotencyState` in\n // `@happyvertical/smrt-agents` lives under `src/server/` (served only by\n // the `./server` export), but the published manifest carried no\n // `importPath`, so consumer registration\n // (`consumer-plugin/index.ts`'s own `determineImportPath`) fell back to\n // the bare package specifier the object was never exported from.\n this.resolveImportPaths(\n manifest,\n options?.packageName,\n options?.packageJson,\n );\n }\n\n /**\n * Drop an `extendsQualified` naming ANOTHER package unless that package's\n * manifest declares the class under exactly that qualified name (#4145).\n *\n * The scanner qualifies a parent from the import it is bound to, but a\n * module can re-export another package's class, and an alias-like specifier\n * (`@app/models`) can look like a package. Neither may become a parent the\n * registry cannot find, so an unconfirmed qualification falls back to the\n * simple `extends` and today's resolution. Same-package qualifications are\n * left alone: they name this manifest's own classes.\n */\n verifyImportedParents(manifest: SmartObjectManifest): void {\n for (const obj of Object.values(manifest.objects)) {\n const parent = obj.extendsQualified;\n if (!parent || !isQualifiedName(parent)) continue;\n const { packageName } = parseQualifiedName(parent);\n if (packageName === (obj.packageName ?? manifest.packageName)) continue;\n const parentManifest = loadExternalManifestSync(packageName, {\n warn: false,\n });\n if (parentManifest && lookupInManifest(parentManifest, parent)) continue;\n logger.debug(\n `[manifest-generator] ${obj.className}: ${packageName} does not declare ${parent}; keeping the unqualified parent \"${obj.extends}\"`,\n );\n delete obj.extendsQualified;\n }\n }\n\n /**\n * The name to resolve an object's parent by: the import-derived qualified\n * name when the scanner traced one (#4145), else the simple `extends`.\n */\n private parentRef(obj: SmartObjectDefinition): string | undefined {\n return obj.extendsQualified || obj.extends;\n }\n\n /**\n * Resolve a parent reference from {@link parentRef}. A qualified reference\n * matches only that package's class (this manifest's, else the dependency's\n * manifest), never a same-named class of another package; a simple one\n * keeps the established local-then-dependency lookup. `child` is skipped so\n * a local class named like its imported parent never resolves to itself.\n */\n private resolveParentDefinition(\n ref: string,\n child: SmartObjectDefinition | undefined,\n manifest: SmartObjectManifest,\n objectsByName: Map<string, SmartObjectDefinition>,\n ): SmartObjectDefinition | undefined {\n let parent: SmartObjectDefinition | undefined = isQualifiedName(ref)\n ? (manifest.objects[ref] as SmartObjectDefinition | undefined)\n : objectsByName.get(ref);\n if (parent === child) parent = undefined;\n if (!parent && manifest.smrtDependencies?.length) {\n parent = this.loadParentFromExternalPackage(\n ref,\n manifest.smrtDependencies,\n objectsByName,\n );\n }\n return parent === child ? undefined : parent;\n }\n\n /**\n * Stamp `importPath` (via {@link determineImportPath}) on every object\n * that does not already have one. Safe to call unconditionally: objects\n * that went through `generateManifest()`'s own inline assignment already\n * carry an `importPath` and are left untouched.\n */\n resolveImportPaths(\n manifest: SmartObjectManifest,\n packageName?: string,\n packageJson?: PackageJsonLike,\n ): void {\n if (!packageName || !packageJson) return;\n\n for (const obj of Object.values(manifest.objects)) {\n if (obj.importPath) continue;\n obj.importPath = this.determineImportPath(packageJson, obj.filePath);\n }\n }\n\n /**\n * Materialize tenantScoped schema fields.\n *\n * Runtime registration already injects tenant fields for\n * `@smrt({ tenantScoped: true })`, but published manifests must contain the\n * same field before schema generation so migrations create `tenant_id`.\n */\n injectTenantScopedFields(manifest: SmartObjectManifest): void {\n for (const objectDef of Object.values(manifest.objects)) {\n this.injectTenantScopedField(objectDef);\n }\n }\n\n private injectTenantScopedField(objectDef: SmartObjectDefinition): void {\n const tenantScoped = objectDef.decoratorConfig?.tenantScoped;\n if (!tenantScoped) {\n return;\n }\n\n const { tenantConfig } = this.normalizeTenantScopedConfig(tenantScoped);\n const fieldName = tenantConfig.field;\n const existingField = objectDef.fields[fieldName];\n const tenancyMeta = {\n isTenantIdField: true,\n ...tenantConfig,\n };\n\n if (existingField) {\n const fieldTypeFailure = this.getTenantScopedFieldTypeFailure(\n objectDef,\n fieldName,\n );\n if (fieldTypeFailure) {\n throw new Error(\n `Tenant-scoped field configuration invalid: ${fieldTypeFailure}`,\n );\n }\n\n existingField._meta = {\n ...existingField._meta,\n sqlType: 'UUID',\n __tenancy: {\n ...existingField._meta?.__tenancy,\n ...tenancyMeta,\n },\n };\n return;\n }\n\n objectDef.fields[fieldName] = {\n type: 'text',\n // Use the normalized tenant mode so the boolean shorthand has the same\n // requiredness in manifests as it does during runtime registration.\n required: tenantConfig.mode === 'required',\n _meta: {\n generated: true,\n source: 'tenantScoped_decorator',\n sqlType: 'UUID',\n __tenancy: tenancyMeta,\n },\n };\n\n logger.debug(\n `[manifest-generator] Injected ${fieldName} field for ${objectDef.className} (tenantScoped: ${JSON.stringify(tenantConfig)})`,\n );\n }\n\n /**\n * Fail the build when a recipe's `options` name a field its model does not\n * declare (#3590). Runs after inherited fields merge, because only the merged\n * manifest knows STI-merged, injected tenant, and framework-base fields\n * (`SmrtHierarchical.parentId`); the scanner sees class bodies alone. The\n * universal `SmrtObject` fields exist on every object but are not manifest\n * fields, so they are accepted by name.\n */\n assertRecipeOptions(manifest: SmartObjectManifest): void {\n const problems: string[] = [];\n for (const recipe of manifest.recipes ?? []) {\n for (const entry of recipe.nav) {\n if (!entry.filter) continue;\n const object = Object.values(manifest.objects).find(\n (candidate) =>\n (candidate.qualifiedName ?? candidate.className) === entry.model,\n );\n if (\n object &&\n !Object.keys(object.fields).includes(entry.filter.field) &&\n !UNIVERSAL_OBJECT_FIELDS.includes(entry.filter.field as never)\n ) {\n problems.push(\n `recipe ${recipe.id}: nav \"${entry.label}\" filters on \"${entry.filter.field}\", which ${object.className} does not declare`,\n );\n }\n }\n for (const [model, options] of Object.entries(recipe.options ?? {})) {\n const object = Object.values(manifest.objects).find(\n (candidate) =>\n (candidate.qualifiedName ?? candidate.className) === model,\n );\n if (!object) {\n problems.push(\n `recipe ${recipe.id}: options name ${model}, which is not an object in this package`,\n );\n continue;\n }\n const declared = new Set([\n ...Object.keys(object.fields),\n ...UNIVERSAL_OBJECT_FIELDS,\n ]);\n for (const field of Object.keys(options.fields ?? {})) {\n if (!declared.has(field)) {\n problems.push(\n `recipe ${recipe.id}: options.${object.className}.fields.${field}: ${object.className} declares no field \"${field}\"; options only refine fields the model already declares`,\n );\n }\n }\n }\n }\n if (problems.length > 0) {\n throw new Error(\n `[manifest-generator] invalid recipe options:\\n ${problems.join('\\n ')}`,\n );\n }\n }\n\n /**\n * Fail the build when a recipe's help refers to a field its models do not\n * declare, or its `fieldRefs` disagree with the Markdown (#3591). Runs on the\n * merged manifest for the same reason as {@link assertRecipeOptions}. The\n * scanner derives `fieldRefs` with its own copy of the reference grammar\n * (it cannot import core); re-deriving here with the real parser means the\n * two can never silently diverge.\n */\n assertRecipeHelp(manifest: SmartObjectManifest): void {\n const problems: string[] = [];\n for (const recipe of manifest.recipes ?? []) {\n if (!recipe.help) continue;\n const models: HelpModel[] = [];\n const sensitiveByModel = new Map<string, Set<string>>();\n for (const model of recipe.models) {\n const object = Object.values(manifest.objects).find(\n (candidate) =>\n (candidate.qualifiedName ?? candidate.className) === model,\n );\n if (!object) continue;\n const sensitive = Object.entries(object.fields)\n .filter(\n ([, field]) =>\n field.sensitive === true || field._meta?.sensitive === true,\n )\n .map(([name]) => name);\n models.push({\n id: model,\n name: object.className,\n // Declared fields only: the universal ones (`slug`, `id`, ...) are not\n // manifest fields, so they never reach the knowledge artifact and a\n // host building its field list from it would drop the step.\n fields: Object.keys(object.fields).map((name) => ({\n name,\n label: name,\n visibility: 'basic',\n })),\n });\n sensitiveByModel.set(object.className, new Set(sensitive));\n }\n for (const problem of validateHelp(recipe.help, models)) {\n problems.push(`recipe ${recipe.id}: help: ${problem}`);\n }\n // Sensitive fields never reach the knowledge artifact, so a host that\n // builds its field list from it would silently drop the step that names\n // one. Keep help prose free of them.\n for (const ref of recipe.help.fieldRefs) {\n const found = findField(ref, models);\n if (\n found &&\n sensitiveByModel.get(found.model.name)?.has(found.field.name)\n ) {\n problems.push(\n `recipe ${recipe.id}: help: {field:${ref}} names a sensitive field; sensitive fields are excluded from the knowledge artifact, so describe it without a field reference`,\n );\n }\n }\n }\n if (problems.length > 0) {\n throw new Error(\n `[manifest-generator] invalid recipe help:\\n ${problems.join('\\n ')}`,\n );\n }\n }\n\n /**\n * Validate every `decoratorConfig.previousQualifiedNames` declaration\n * (#3338). The declaration rides into the manifest verbatim — it is the\n * lazy loader's alias index — so a malformed or colliding alias must stop\n * the build rather than ship a manifest the runtime will refuse:\n *\n * - an array of scoped `@scope/package:ClassName` strings, each listed once;\n * - never the object's own qualified name, nor any object of this manifest;\n * - never declared by two objects of this manifest.\n */\n assertQualifiedNameAliases(manifest: SmartObjectManifest): void {\n const ownNames = new Set<string>();\n for (const [key, obj] of Object.entries(manifest.objects)) {\n ownNames.add(obj.qualifiedName ?? key);\n }\n const claimedBy = new Map<string, string>();\n for (const key of Object.keys(manifest.objects).sort(compareText)) {\n const obj = manifest.objects[key];\n const owner = obj.qualifiedName ?? key;\n const declared = (\n obj.decoratorConfig as { previousQualifiedNames?: unknown } | undefined\n )?.previousQualifiedNames;\n if (declared === undefined) continue;\n if (!Array.isArray(declared)) {\n throw new Error(\n `[manifest-generator] ${owner}: previousQualifiedNames must be an array of qualified names (\"@package/name:ClassName\").`,\n );\n }\n const aliases = readPreviousQualifiedNames(obj.decoratorConfig);\n if (aliases.length !== declared.length) {\n throw new Error(\n `[manifest-generator] ${owner}: previousQualifiedNames must contain only string literals.`,\n );\n }\n const seen = new Set<string>();\n for (const alias of aliases) {\n if (!isQualifiedNameAliasFormat(alias)) {\n throw new Error(\n `[manifest-generator] ${owner}: previousQualifiedNames entry \"${alias}\" is not a qualified name (\"@package/name:ClassName\").`,\n );\n }\n if (seen.has(alias)) {\n throw new Error(\n `[manifest-generator] ${owner}: previousQualifiedNames lists \"${alias}\" more than once.`,\n );\n }\n seen.add(alias);\n if (ownNames.has(alias)) {\n throw new Error(\n `[manifest-generator] ${owner}: previousQualifiedNames \"${alias}\" names a live object of this package; an alias may only name a class that no longer exists.`,\n );\n }\n const other = claimedBy.get(alias);\n if (other) {\n throw new Error(\n `[manifest-generator] previousQualifiedNames \"${alias}\" is declared by both ${other} and ${owner}; an old name can resolve to only one class.`,\n );\n }\n claimedBy.set(alias, owner);\n }\n }\n }\n\n /**\n * Validate and resolve presentation metadata (#3599), failing the build on\n * a declaration no host could honor:\n *\n * - `@field({ ui: { widget } })` must name a known widget the field's type\n * accepts (every widget is text-only; `currency` is an ISO 4217 code\n * picker, not an amount).\n * - `@smrt({ display: { label } })` must name an own, non-sensitive,\n * non-transient, non-relationship field.\n * - A selector slot's `selects` must resolve when it names this package.\n *\n * Also stamps each object's resolved `displayLabelField` (the declared field,\n * else the first of name/title/label/code).\n */\n applyUiMetadata(manifest: SmartObjectManifest): void {\n const failures: string[] = [];\n\n for (const key of Object.keys(manifest.objects).sort(compareText)) {\n const obj = manifest.objects[key];\n const owner = obj.qualifiedName ?? key;\n\n for (const [fieldName, field] of Object.entries(obj.fields)) {\n const role = (field._meta as { role?: unknown } | undefined)?.role;\n if (role !== undefined) {\n if (!isRelationshipRole(role)) {\n failures.push(\n `${owner}.${fieldName}: role ${JSON.stringify(role)} is not one of ${RELATIONSHIP_ROLES.join(', ')}.`,\n );\n } else if (\n field.type !== 'foreignKey' &&\n field.type !== 'crossPackageRef'\n ) {\n failures.push(\n `${owner}.${fieldName}: role \"${role}\" needs a foreignKey or crossPackageRef field, but this field is ${field.type}.`,\n );\n }\n }\n const ui = field._meta?.ui as\n | { widget?: unknown; format?: unknown }\n | undefined;\n if (!ui || typeof ui !== 'object') continue;\n if (ui.format !== undefined) {\n if (!isFieldUIFormat(ui.format)) {\n failures.push(\n `${owner}.${fieldName}: ui.format ${JSON.stringify(ui.format)} is not one of ${FIELD_UI_FORMATS.join(', ')}.`,\n );\n } else if (!FIELD_UI_FORMAT_TYPES[ui.format].includes(field.type)) {\n failures.push(\n `${owner}.${fieldName}: ui.format \"${ui.format}\" needs a field of type ${FIELD_UI_FORMAT_TYPES[ui.format].join(' or ')}, but this field is ${field.type}.`,\n );\n }\n }\n if (ui.widget === undefined) continue;\n if (!isFieldUIWidget(ui.widget)) {\n failures.push(\n `${owner}.${fieldName}: ui.widget ${JSON.stringify(ui.widget)} is not one of ${FIELD_UI_WIDGETS.join(', ')}.`,\n );\n } else if (!FIELD_UI_WIDGET_TYPES[ui.widget].includes(field.type)) {\n failures.push(\n `${owner}.${fieldName}: ui.widget \"${ui.widget}\" needs a field of type ${FIELD_UI_WIDGET_TYPES[ui.widget].join(' or ')}, but this field is ${field.type}.`,\n );\n }\n }\n\n const display = (obj.decoratorConfig as { display?: unknown } | undefined)\n ?.display;\n let declared: string | undefined;\n if (display !== undefined) {\n const label =\n display && typeof display === 'object'\n ? (display as { label?: unknown }).label\n : undefined;\n if (\n label !== undefined &&\n (typeof label !== 'string' || label === '')\n ) {\n failures.push(\n `${owner}: display.label must be the name of an own field (a string literal), not ${JSON.stringify(label)}.`,\n );\n } else if (typeof label === 'string') {\n const problem = displayLabelFieldProblem(obj.fields, label);\n if (problem) {\n failures.push(\n `${owner}: display.label \"${label}\" cannot label a record: ${problem}.`,\n );\n } else {\n declared = label;\n }\n } else if (display === null || typeof display !== 'object') {\n failures.push(`${owner}: display must be an object ({ label }).`);\n }\n }\n const resolved = resolveDisplayLabelField(obj.fields, declared);\n if (resolved) {\n obj.displayLabelField = resolved;\n } else {\n delete obj.displayLabelField;\n }\n }\n\n const own = new Set<string>();\n for (const [key, obj] of Object.entries(manifest.objects)) {\n own.add(obj.qualifiedName ?? key);\n }\n for (const [slotId, selector] of Object.entries(\n manifest.uiSelectors ?? {},\n )) {\n const target = selector.selects;\n const targetPackage = target.slice(0, target.indexOf(':'));\n if (\n manifest.packageName &&\n targetPackage === manifest.packageName &&\n !own.has(target)\n ) {\n failures.push(\n `UI slot \"${slotId}\" selects ${target}, which is not an object of ${manifest.packageName}.`,\n );\n }\n }\n\n if (failures.length > 0) {\n throw new Error(\n `UI metadata invalid:\\n${failures.map((f) => ` - ${f}`).join('\\n')}`,\n );\n }\n }\n\n assertTenantScopedSchemaContract(manifest: SmartObjectManifest): void {\n const failures: string[] = [];\n\n for (const objectDef of Object.values(manifest.objects)) {\n const tenantScoped = objectDef.decoratorConfig?.tenantScoped;\n if (!tenantScoped) {\n continue;\n }\n\n const { tenantConfig } = this.normalizeTenantScopedConfig(tenantScoped);\n const fieldName = tenantConfig.field;\n const columnName = toSnakeCase(fieldName);\n\n if (!objectDef.fields[fieldName]) {\n failures.push(\n `${objectDef.className}: missing tenant-scoped field \"${fieldName}\"`,\n );\n continue;\n }\n\n const fieldTypeFailure = this.getTenantScopedFieldTypeFailure(\n objectDef,\n fieldName,\n );\n if (fieldTypeFailure) {\n failures.push(fieldTypeFailure);\n continue;\n }\n\n const schemaOwner = this.getTenantScopedSchemaOwner(objectDef, manifest);\n const schemaOwnerContext =\n schemaOwner === objectDef\n ? ''\n : ` on STI base \"${schemaOwner.className}\"`;\n\n if (!schemaOwner.schema?.columns) {\n failures.push(\n `${objectDef.className}: schema has not been generated for tenant-scoped column \"${columnName}\"${schemaOwnerContext}`,\n );\n continue;\n }\n\n if (!schemaOwner.schema.columns[columnName]) {\n failures.push(\n `${objectDef.className}: schema is missing tenant-scoped column \"${columnName}\"${schemaOwnerContext}`,\n );\n }\n }\n\n if (failures.length > 0) {\n throw new Error(\n `Tenant-scoped schema contract failed:\\n${failures\n .map((failure) => ` - ${failure}`)\n .join('\\n')}`,\n );\n }\n }\n\n private getTenantScopedSchemaOwner(\n objectDef: SmartObjectDefinition,\n manifest: SmartObjectManifest,\n ): SmartObjectDefinition {\n if (!this.isSTIChildClass(objectDef, manifest)) {\n return objectDef;\n }\n\n const stiBase = this.findSTIBaseInfo(objectDef, manifest);\n if (!stiBase) {\n return objectDef;\n }\n\n const localBase = Object.values(manifest.objects).find(\n (candidate) => candidate.className === stiBase.className,\n );\n\n return localBase ?? objectDef;\n }\n\n private getTenantScopedFieldTypeFailure(\n objectDef: SmartObjectDefinition,\n fieldName: string,\n ): string | undefined {\n const field = objectDef.fields[fieldName];\n if (!field) {\n return undefined;\n }\n\n if (field.type !== 'text' && field.type !== 'foreignKey') {\n return `${objectDef.className}: tenant-scoped field \"${fieldName}\" must use type \"text\" or \"foreignKey\"; received \"${field.type}\"`;\n }\n\n const sqlType = field._meta?.sqlType;\n if (sqlType && !['TEXT', 'UUID'].includes(String(sqlType).toUpperCase())) {\n return `${objectDef.className}: tenant-scoped field \"${fieldName}\" must use SQL type \"UUID\" or legacy \"TEXT\"; received \"${sqlType}\"`;\n }\n\n return undefined;\n }\n\n private normalizeTenantScopedConfig(tenantScoped: unknown): {\n tenantConfig: {\n mode: string;\n field: string;\n autoFilter: boolean;\n autoPopulate: boolean;\n allowSuperAdminBypass: boolean;\n };\n } {\n const tenantOptions: TenantScopedOptions =\n typeof tenantScoped === 'boolean'\n ? {}\n : (tenantScoped as TenantScopedOptions);\n\n return {\n tenantConfig: {\n mode: tenantOptions.mode ?? 'required',\n field: tenantOptions.field ?? 'tenantId',\n autoFilter: tenantOptions.autoFilter ?? true,\n autoPopulate: tenantOptions.autoPopulate ?? true,\n allowSuperAdminBypass: tenantOptions.allowSuperAdminBypass ?? false,\n },\n };\n }\n\n /**\n * Generate pre-computed validation rules for all objects in the manifest.\n *\n * This extracts validation constraints (required, min, max, minLength, maxLength, pattern)\n * from field definitions and stores them as serializable rules in the manifest.\n *\n * At runtime, these rules can be evaluated without creating validator closures,\n * significantly reducing CLI startup time for projects with many SMRT objects.\n *\n * @param manifest - The manifest to process in-place\n */\n generateValidationRules(manifest: SmartObjectManifest): void {\n for (const [name, obj] of Object.entries(manifest.objects)) {\n const rules: ValidationRule[] = [];\n let skippedAutoPopulatedTenantRequiredRule = false;\n\n for (const [fieldName, field] of Object.entries(obj.fields)) {\n // Skip transient fields (they're not persisted, so no validation needed)\n if (field.transient || field._meta?.transient) {\n continue;\n }\n\n const options = field._meta || {};\n\n // Required field rule\n const isAutoPopulatedTenantField =\n options.__tenancy?.isTenantIdField === true &&\n options.__tenancy.autoPopulate !== false;\n if (\n (options.required || field.required) &&\n !isAutoPopulatedTenantField\n ) {\n rules.push({\n field: fieldName,\n rule: 'required',\n fieldType: field.type,\n });\n } else if (\n isAutoPopulatedTenantField &&\n (options.required || field.required)\n ) {\n // Tenant IDs can be required in the manifest and database while still\n // being absent at this pre-interceptor validation stage. Tenancy's\n // beforeSave hook stamps them from the active context before writing.\n skippedAutoPopulatedTenantRequiredRule = true;\n }\n\n // Numeric range rules (for integer, decimal fields)\n if (field.type === 'integer' || field.type === 'decimal') {\n if (options.min !== undefined || field.min !== undefined) {\n rules.push({\n field: fieldName,\n rule: 'min',\n value: options.min ?? field.min,\n fieldType: field.type,\n });\n }\n\n if (options.max !== undefined || field.max !== undefined) {\n rules.push({\n field: fieldName,\n rule: 'max',\n value: options.max ?? field.max,\n fieldType: field.type,\n });\n }\n }\n\n // String length rules (for text fields)\n if (field.type === 'text') {\n if (\n options.minLength !== undefined ||\n field.minLength !== undefined\n ) {\n rules.push({\n field: fieldName,\n rule: 'minLength',\n value: options.minLength ?? field.minLength,\n fieldType: field.type,\n });\n }\n\n if (\n options.maxLength !== undefined ||\n field.maxLength !== undefined\n ) {\n rules.push({\n field: fieldName,\n rule: 'maxLength',\n value: options.maxLength ?? field.maxLength,\n fieldType: field.type,\n });\n }\n\n // Pattern rule (regex validation)\n // Note: Custom validator functions (options.validate) cannot be serialized\n // and will fall back to compiled validators at runtime\n // Note: Pattern is only available in field options, not in FieldDefinition\n const pattern = options.pattern;\n if (pattern) {\n rules.push({\n field: fieldName,\n rule: 'pattern',\n // RegExp patterns expose `.source`; a JSON-collapsed RegExp ({})\n // has none, preserving the prior `undefined` value exactly.\n value:\n typeof pattern === 'string'\n ? pattern\n : (pattern as { source?: string }).source,\n fieldType: field.type,\n });\n }\n }\n }\n\n // An explicit empty list is meaningful when the sole required field is\n // auto-populated by tenancy: it prevents runtime registration from\n // recompiling a pre-interceptor required validator for that field.\n if (rules.length > 0 || skippedAutoPopulatedTenantRequiredRule) {\n obj.validationRules = rules;\n }\n }\n }\n\n /**\n * Generate pre-computed schemas for all objects in the manifest.\n *\n * This enables external package consumers to use pre-generated schemas\n * without calling generateSchema() at runtime, eliminating latency.\n *\n * IMPORTANT: For STI classes, we aggregate ALL descendants from both local\n * and external packages to ensure complete schemas are generated.\n *\n * This method is public to allow external callers (like OXC scanner) to use it.\n *\n * @param manifest - The manifest to process in-place\n */\n generateSchemas(manifest: SmartObjectManifest): void {\n const generator = new SchemaGenerator();\n\n // Create aggregated manifest that includes external package objects\n // This ensures STI schema generation finds ALL descendants\n const aggregatedManifest = this.createAggregatedManifest(manifest);\n const schemaClasses = new Map(\n Object.values(aggregatedManifest.objects).map((obj) => [\n obj.className,\n obj,\n ]),\n );\n\n // An external class with the same simple name cannot replace a local item.\n for (const obj of Object.values(manifest.objects))\n schemaClasses.set(obj.className, obj);\n\n for (const [name, obj] of Object.entries(manifest.objects)) {\n // Collections access their item model's table; an independent schema can\n // contradict that model's tenant/conflict identity during aggregation.\n if (this.extendsCollection(obj, schemaClasses)) {\n delete obj.schema;\n continue;\n }\n if (FRAMEWORK_ABSTRACT_BASE_NAMES.has(obj.className)) {\n continue;\n }\n\n // Determine table name (may have been inherited from external STI base)\n // Use obj.className (PascalCase) for consistent table name derivation with runtime\n const tableName =\n obj.decoratorConfig?.tableName ||\n this.classNameToTableName(obj.className);\n\n // Check if this is an STI class. `mergeInheritedFields()` copies the\n // base's `tableStrategy` onto every descendant, so both the root and\n // its children arrive here; `isSTIChildClass` covers a child whose\n // strategy was not inherited.\n if (\n obj.decoratorConfig?.tableStrategy === 'sti' ||\n this.isSTIChildClass(obj, manifest)\n ) {\n // Every class in an STI hierarchy — root, local child, or a child of\n // an EXTERNAL base — carries the schema of the ONE shared table,\n // generated from the ROOT base so descendant discovery, the\n // discriminator-partial unique indexes and the base-declared /\n // descendant-declared distinction are computed against the same\n // hierarchy on every class (#527, #2359). A child generated as if it\n // were the root would treat its own descendant-only `unique: true`\n // fields as base-declared and emit a full unique index that\n // `getAllSchemasAsDefinitions()` then merges into the table beside\n // the correct partial one.\n const stiRoot = this.findSTIBaseInfo(obj, manifest);\n const rootKey = stiRoot\n ? (this.resolveManifestKey(stiRoot.className, aggregatedManifest) ??\n stiRoot.className)\n : name;\n const rootTableName = stiRoot?.tableName || tableName;\n const rootConfig =\n aggregatedManifest.objects[rootKey]?.decoratorConfig ??\n obj.decoratorConfig;\n\n logger.debug(\n `[manifest-generator] Generating STI schema for ${name} (root: ${rootKey}, table: ${rootTableName})`,\n );\n\n // Use aggregated manifest to find descendants from ALL packages\n obj.schema = generator.generateSTISchemaFromManifest(\n rootKey,\n rootTableName,\n obj.fields,\n aggregatedManifest,\n rootConfig,\n );\n this.applySqlTypeOverrides(obj);\n } else {\n // CTI class - generate individual table schema\n logger.debug(\n `[manifest-generator] Generating CTI schema for ${name} (table: ${tableName})`,\n );\n\n obj.schema = generator.generateCTISchemaFromManifest(\n name,\n tableName,\n obj.fields,\n obj.decoratorConfig,\n );\n this.applySqlTypeOverrides(obj);\n }\n }\n\n this.resolveSamePackageForeignKeyColumnTypes(manifest, generator);\n\n // Preserve collection metadata, but take persistence identity from the item\n // model only after every model schema (including FK repair) is complete.\n for (const obj of Object.values(manifest.objects)) {\n if (!this.extendsCollection(obj, schemaClasses)) continue;\n let current: SmartObjectDefinition | undefined = obj;\n const visited = new Set<SmartObjectDefinition>();\n while (current && !visited.has(current)) {\n visited.add(current);\n const item = this.findItemClass(\n current,\n aggregatedManifest,\n schemaClasses,\n );\n if (item?.schema && !this.extendsCollection(item, schemaClasses)) {\n obj.schema = structuredClone(item.schema);\n break;\n }\n current = current.extends\n ? schemaClasses.get(current.extends)\n : undefined;\n }\n }\n }\n\n /** A report model's generated surface defaults to `list`/`get`. */\n applyReportSurfaceDefaults(manifest: SmartObjectManifest): void {\n for (const obj of Object.values(manifest.objects)) {\n if (!obj.decoratorConfig?.report) continue;\n obj.decoratorConfig.api ??= { include: ['list', 'get'] };\n obj.decoratorConfig.mcp ??= { include: ['list', 'get'] };\n }\n }\n\n normalizeReportObjects(manifest: SmartObjectManifest): void {\n this.applyReportSurfaceDefaults(manifest);\n for (const obj of Object.values(manifest.objects)) {\n if (!obj.decoratorConfig?.report) continue;\n\n if (obj.decoratorConfig.conflictColumns) continue;\n\n const tenantScoped = obj.decoratorConfig.tenantScoped;\n const tenantField =\n tenantScoped && typeof tenantScoped === 'object'\n ? tenantScoped.field || 'tenantId'\n : tenantScoped\n ? 'tenantId'\n : undefined;\n const tenantColumn =\n tenantField && obj.fields[tenantField] ? toSnakeCase(tenantField) : '';\n\n const conflictColumns = Object.entries(obj.fields)\n .filter(([, field]) => {\n const kind = field._meta?.__report?.kind;\n return kind === 'group' || kind === 'bucket';\n })\n .map(([fieldName]) => toSnakeCase(fieldName));\n\n obj.decoratorConfig.conflictColumns =\n conflictColumns.length > 0\n ? [...(tenantColumn ? [tenantColumn] : []), ...conflictColumns]\n : ['id'];\n }\n }\n\n normalizeReportTenantScope(manifest: SmartObjectManifest): void {\n for (const obj of Object.values(manifest.objects)) {\n if (!obj.decoratorConfig?.report) continue;\n obj.decoratorConfig.tenantScoped ??= { mode: 'optional' };\n }\n }\n\n /**\n * Materialize the tenant-aware default conflict target (#2360).\n *\n * A tenant-owned class — tenant-scoped, or carrying an undeclared\n * `tenantId` field (`resolveOwnershipTenantColumn()`) — that declares no\n * `@smrt({ conflictColumns })` keys on `[tenant column, ...natural key]` — `(tenant_id, slug, context)` for\n * a class-per-table object, `(tenant_id, slug, context, _meta_type)` for a\n * single-table hierarchy — so two tenants can each own the same slug and\n * neither `save()` adopts the other's row. Writing the resolved key into\n * `decoratorConfig.conflictColumns` (mirroring `normalizeReportObjects`)\n * makes the manifest, the generated schema, the knowledge artifact and\n * `ObjectRegistry.getConflictColumns()` read one value.\n *\n * Only schema owners are normalized: an STI child inherits the table (and\n * therefore the key) from its root, and `getConflictColumns()` resolves a\n * child through its root at runtime. Explicit `conflictColumns` and\n * `@report` classes (keyed by `normalizeReportObjects`) are left alone.\n * Runs after `injectTenantScopedFields()` and `mergeInheritedFields()` so\n * the tenant field and the inherited `tableStrategy` are in place, and\n * before `generateSchemas()`.\n */\n normalizeConflictColumns(manifest: SmartObjectManifest): void {\n for (const obj of Object.values(manifest.objects)) {\n if (!obj.decoratorConfig) continue;\n if (FRAMEWORK_ABSTRACT_BASE_NAMES.has(obj.className)) continue;\n if (obj.decoratorConfig.conflictColumns) continue;\n if (obj.decoratorConfig.report) continue;\n if (this.isSTIChildClass(obj, manifest)) continue;\n\n const tenantScoped = obj.decoratorConfig.tenantScoped;\n const declaredTenantColumn = tenantScoped\n ? resolveTenantColumn(\n this.normalizeTenantScopedConfig(tenantScoped).tenantConfig.field,\n (fieldName) => Boolean(obj.fields[fieldName]),\n toSnakeCase,\n )\n : undefined;\n // A class that carries `tenantId` without declaring tenancy (a consumer\n // registers it with the tenancy interceptor at runtime) is still\n // tenant-OWNED: its natural key is unique per tenant too.\n const tenantColumn = resolveOwnershipTenantColumn(\n declaredTenantColumn,\n (column) =>\n Object.keys(obj.fields).some(\n (fieldName) => toSnakeCase(fieldName) === column,\n ),\n );\n if (!tenantColumn) continue;\n\n obj.decoratorConfig.conflictColumns = defaultConflictColumns(\n obj.decoratorConfig.tableStrategy === 'sti' ? 'sti' : 'cti',\n tenantColumn,\n );\n }\n }\n\n private resolveSamePackageForeignKeyColumnTypes(\n manifest: SmartObjectManifest,\n generator: SchemaGeneratorLike,\n ): void {\n // One representative schema per table for target-id lookups, plus EVERY\n // schema that describes a table: each class of an STI hierarchy carries a\n // copy of the shared table's schema (#2359), and every copy must receive\n // the same reconciled type or `getAllSchemasAsDefinitions()`'s\n // first-wins column merge can surface an unreconciled one.\n const schemaByTable = new Map<string, ManifestSchema>();\n const schemasByTable = new Map<string, ManifestSchema[]>();\n const ownerBySchema = new Map<\n ManifestSchema,\n { name: string; obj: SmartObjectDefinition }\n >();\n const changedSchemas = new Set<ManifestSchema>();\n const objectsByName = new Map<string, SmartObjectDefinition>();\n\n for (const [name, obj] of Object.entries(manifest.objects)) {\n objectsByName.set(obj.className, obj);\n objectsByName.set(obj.className.toLowerCase(), obj);\n if (obj.schema?.tableName) {\n schemaByTable.set(obj.schema.tableName, obj.schema);\n const siblings = schemasByTable.get(obj.schema.tableName) ?? [];\n siblings.push(obj.schema);\n schemasByTable.set(obj.schema.tableName, siblings);\n ownerBySchema.set(obj.schema, { name, obj });\n }\n }\n\n for (const obj of Object.values(manifest.objects)) {\n const sourceTable = this.getObjectTableName(obj);\n if (!sourceTable) {\n continue;\n }\n\n const sourceSchemas = schemasByTable.get(sourceTable);\n if (!sourceSchemas || sourceSchemas.length === 0) {\n continue;\n }\n\n for (const [fieldName, field] of Object.entries(obj.fields || {})) {\n if (\n field.type !== 'foreignKey' ||\n !field.related ||\n field._meta?.__tenancy?.isTenantIdField === true\n ) {\n continue;\n }\n\n const emitConstraint = field._meta?.constraint !== false;\n\n const columnName = toSnakeCase(fieldName);\n const targetSchema = this.findForeignKeyTargetSchema(\n field.related,\n manifest,\n schemaByTable,\n obj.packageName,\n );\n if (!targetSchema) {\n for (const sourceSchema of sourceSchemas) {\n const sourceColumn = sourceSchema.columns[columnName];\n if (sourceColumn?.foreignKey) {\n sourceSchema.columns[columnName] = {\n ...sourceColumn,\n foreignKey: undefined,\n };\n changedSchemas.add(sourceSchema);\n }\n }\n continue;\n }\n\n const [, declaredTargetColumn] = field.related.split('.');\n const targetColumn =\n declaredTargetColumn ||\n Object.entries(targetSchema.columns).find(\n ([, definition]) => definition.primaryKey === true,\n )?.[0] ||\n 'id';\n const targetIdType = targetSchema.columns[targetColumn]?.type;\n const conflictOwner =\n this.findSTIBase(obj, objectsByName, manifest) ?? obj;\n const conflictColumns = new Set(\n (conflictOwner.decoratorConfig?.conflictColumns || []).map((column) =>\n toSnakeCase(column),\n ),\n );\n const { action } = resolveForeignKeyDeleteAction({\n declared: field._meta?.onDelete,\n isConflictColumn: conflictColumns.has(columnName),\n isTenantIdField: false,\n columnName,\n });\n\n for (const sourceSchema of sourceSchemas) {\n const sourceColumn = sourceSchema.columns[columnName];\n if (!sourceColumn) {\n continue;\n }\n const nextColumn = {\n ...sourceColumn,\n ...(!field._meta?.sqlType && targetIdType\n ? { type: targetIdType }\n : {}),\n foreignKey: emitConstraint\n ? {\n table: targetSchema.tableName,\n column: targetColumn,\n onDelete: action,\n onUpdate: resolveForeignKeyUpdateAction(\n field._meta?.onUpdate,\n ),\n ...(typeof field._meta?.constraint === 'object'\n ? { engines: [...field._meta.constraint.engines] }\n : {}),\n }\n : undefined,\n };\n if (JSON.stringify(nextColumn) === JSON.stringify(sourceColumn)) {\n continue;\n }\n sourceSchema.columns[columnName] = nextColumn;\n changedSchemas.add(sourceSchema);\n }\n }\n }\n\n for (const schema of changedSchemas) {\n this.refreshManifestSchemaDDL(\n schema,\n generator,\n ownerBySchema.get(schema),\n manifest,\n );\n }\n }\n\n private findForeignKeyTargetSchema(\n related: string,\n manifest: SmartObjectManifest,\n schemaByTable: Map<string, ManifestSchema>,\n sourcePackageName?: string,\n ): ManifestSchema | undefined {\n const relatedTarget = related.split('.')[0];\n if (schemaByTable.has(relatedTarget)) {\n return schemaByTable.get(relatedTarget);\n }\n\n const candidates = Object.values(manifest.objects).filter(\n (candidate) =>\n candidate.className === relatedTarget ||\n candidate.qualifiedName === relatedTarget ||\n candidate.name === relatedTarget ||\n candidate.decoratorConfig?.tableName === relatedTarget ||\n candidate.schema?.tableName === relatedTarget,\n );\n const localTarget = candidates.find(\n (candidate) => candidate.packageName === sourcePackageName,\n );\n if (!localTarget && candidates.length > 1) {\n throw new Error(\n `Ambiguous foreign key target ${relatedTarget} from package ${sourcePackageName}`,\n );\n }\n const targetObj = localTarget ?? candidates[0];\n\n if (!targetObj && relatedTarget.includes(':')) {\n return undefined;\n }\n\n const targetTable = targetObj\n ? this.getObjectTableName(targetObj)\n : this.classNameToTableName(relatedTarget);\n\n return targetTable ? schemaByTable.get(targetTable) : undefined;\n }\n\n private getObjectTableName(obj: SmartObjectDefinition): string | undefined {\n return (\n obj.schema?.tableName ||\n obj.decoratorConfig?.tableName ||\n this.classNameToTableName(obj.className)\n );\n }\n\n private refreshManifestSchemaDDL(\n schema: ManifestSchema,\n generator: SchemaGeneratorLike,\n owner: { name: string; obj: SmartObjectDefinition } | undefined,\n manifest: SmartObjectManifest,\n ): void {\n const columns: Record<string, ColumnDefinition> = {};\n for (const [name, column] of Object.entries(schema.columns)) {\n columns[name] = {\n // ManifestColumnDefinition stores `type` as a plain string; it is\n // always a valid SQLDataType for DDL rendering.\n type: column.type as SQLDataType,\n primaryKey: column.primaryKey,\n notNull: column.notNull,\n unique: column.unique,\n defaultValue: column.default,\n foreignKey: column.foreignKey ? { ...column.foreignKey } : undefined,\n };\n }\n\n const schemaDefinition: SchemaDefinition = {\n tableName: schema.tableName,\n columns,\n indexes: (schema.indexes || []).map((index) => ({\n name: index.name,\n columns: index.columns,\n unique: index.unique,\n ...(index.nullsNotDistinct ? { nullsNotDistinct: true } : {}),\n where: index.where,\n jsonPath: index.jsonPath,\n })),\n triggers: [],\n foreignKeys: Object.entries(columns).flatMap(([column, definition]) =>\n definition.foreignKey\n ? [\n {\n column,\n referencesTable: definition.foreignKey.table,\n referencesColumn: definition.foreignKey.column,\n onDelete: definition.foreignKey.onDelete,\n onUpdate: definition.foreignKey.onUpdate,\n ...(definition.foreignKey.engines\n ? { engines: definition.foreignKey.engines }\n : {}),\n },\n ]\n : [],\n ),\n dependencies: Object.values(columns)\n .flatMap((definition) =>\n definition.foreignKey ? [definition.foreignKey.table] : [],\n )\n .filter((dependency) => dependency !== schema.tableName),\n version: schema.version,\n packageName: '',\n };\n\n schema.ddl = generator.generateSQL(schemaDefinition);\n schema.version = this.computeManifestSchemaVersion(schema, owner, manifest);\n }\n\n private computeManifestSchemaVersion(\n schema: ManifestSchema,\n owner: { name: string; obj: SmartObjectDefinition } | undefined,\n manifest: SmartObjectManifest,\n ): string {\n if (schema.columns._meta_type && owner) {\n const baseClassName =\n owner.obj.decoratorConfig?.tableStrategy === 'sti'\n ? owner.name\n : this.findSTIBaseInfo(owner.obj, manifest)?.className || owner.name;\n\n return createHash('sha256')\n .update(\n JSON.stringify({\n columns: schema.columns,\n baseClassName,\n descendants: this.findDescendantsInManifest(\n baseClassName,\n manifest,\n ),\n }),\n )\n .digest('hex')\n .substring(0, 8);\n }\n\n return createHash('sha256')\n .update(\n JSON.stringify({\n columns: schema.columns,\n className: owner?.name || schema.tableName,\n }),\n )\n .digest('hex')\n .substring(0, 8);\n }\n\n private findDescendantsInManifest(\n baseClassName: string,\n manifest: SmartObjectManifest,\n visited: Set<string> = new Set(),\n ): string[] {\n const descendants: string[] = [];\n if (visited.has(baseClassName)) {\n return descendants;\n }\n visited.add(baseClassName);\n\n const baseClassLower = this.simpleClassName(baseClassName).toLowerCase();\n\n for (const [name, obj] of Object.entries(manifest.objects)) {\n const classNameLower = this.simpleClassName(obj.className).toLowerCase();\n const extendsLower = obj.extends\n ? this.simpleClassName(obj.extends).toLowerCase()\n : undefined;\n\n if (\n classNameLower === baseClassLower &&\n extendsLower === baseClassLower\n ) {\n continue;\n }\n\n // An import-qualified parent names its package: a same-named base of\n // another package is not this class's ancestor (#4145).\n if (\n extendsLower === baseClassLower &&\n !this.qualifiedParentExcludes(obj, baseClassName)\n ) {\n descendants.push(name);\n descendants.push(\n ...this.findDescendantsInManifest(name, manifest, visited),\n );\n }\n }\n\n return descendants;\n }\n\n /**\n * Whether `obj`'s import-qualified parent rules out `baseClassName` (a\n * qualified name of another class with the same simple name).\n */\n private qualifiedParentExcludes(\n obj: SmartObjectDefinition,\n baseClassName: string,\n ): boolean {\n return (\n !!obj.extendsQualified &&\n isQualifiedName(baseClassName) &&\n obj.extendsQualified !== baseClassName\n );\n }\n\n private applySqlTypeOverrides(obj: SmartObjectDefinition): void {\n if (!obj.schema?.columns) {\n return;\n }\n\n for (const [fieldName, field] of Object.entries(obj.fields || {})) {\n const sqlType = field?._meta?.sqlType;\n const referenceKind = this.getReferenceKind(field);\n if (!sqlType && !referenceKind) {\n continue;\n }\n\n const columnName = toSnakeCase(fieldName);\n if (!obj.schema.columns[columnName]) {\n continue;\n }\n\n const column = {\n ...obj.schema.columns[columnName],\n ...(sqlType ? { type: String(sqlType).toUpperCase() } : {}),\n ...(referenceKind ? { referenceKind } : {}),\n };\n // A `''` initializer (e.g. `tenantId: string = ''`) is not a uuid: as a\n // column default PostgreSQL stores `(''::text)::uuid` unevaluated and\n // every INSERT that omits the column fails with 22P02. An identifier\n // column has no default.\n if (\n String(column.type).toUpperCase() === 'UUID' &&\n column.default === ''\n ) {\n delete column.default;\n }\n obj.schema.columns[columnName] = column;\n }\n }\n\n private getReferenceKind(\n field: SmartObjectDefinition['fields'][string] | undefined,\n ): ManifestColumnDefinition['referenceKind'] | undefined {\n if (field?._meta?.__tenancy?.isTenantIdField) {\n return 'tenantId';\n }\n\n if (field?.type === 'foreignKey') {\n return 'foreignKey';\n }\n\n if (field?.type === 'crossPackageRef') {\n return 'crossPackageRef';\n }\n\n return undefined;\n }\n\n /**\n * Create an aggregated manifest that includes objects from all external packages\n *\n * This is used for STI schema generation to ensure ALL descendants are found,\n * regardless of which package they're defined in.\n *\n * @param manifest - The local manifest\n * @returns Aggregated manifest with local + external objects\n */\n private createAggregatedManifest(\n manifest: SmartObjectManifest,\n ): SmartObjectManifest {\n // Start with a copy of local objects\n const aggregatedObjects: Record<string, SmartObjectDefinition> = {\n ...manifest.objects,\n };\n\n // Load and merge external package objects\n if (manifest.smrtDependencies && manifest.smrtDependencies.length > 0) {\n for (const packageName of manifest.smrtDependencies) {\n const externalManifest = loadExternalManifestSync(packageName);\n if (externalManifest) {\n // Merge external objects (local objects take precedence on collision)\n for (const [name, obj] of Object.entries(externalManifest.objects)) {\n if (!aggregatedObjects[name]) {\n aggregatedObjects[name] = obj;\n }\n }\n\n logger.debug(\n `[manifest-generator] Aggregated ${Object.keys(externalManifest.objects).length} objects from ${packageName}`,\n );\n }\n }\n }\n\n return {\n ...manifest,\n objects: aggregatedObjects,\n };\n }\n\n /**\n * Check if an object is an STI child class (inherits from STI base)\n *\n * Walks up the inheritance chain to find if any ancestor has tableStrategy: 'sti'.\n * Also checks external SMRT packages for parent class definitions.\n */\n private isSTIChildClass(\n obj: SmartObjectDefinition,\n manifest: SmartObjectManifest,\n ): boolean {\n if (!obj.extends) return false;\n\n // Build a lookup map for efficient access\n const objectsByName = new Map<string, SmartObjectDefinition>();\n for (const [_name, objDef] of Object.entries(manifest.objects)) {\n objectsByName.set(objDef.className, objDef);\n objectsByName.set(objDef.className.toLowerCase(), objDef);\n }\n\n // Walk up the inheritance chain looking for STI base\n let currentClass: string | undefined = this.parentRef(obj);\n const visited = new Set<string>();\n\n while (currentClass) {\n if (visited.has(currentClass)) break;\n visited.add(currentClass);\n\n // Local first, then external SMRT packages; a qualified parent only\n // resolves to its own package's class (#4145).\n const parentObj = this.resolveParentDefinition(\n currentClass,\n obj,\n manifest,\n objectsByName,\n );\n\n if (!parentObj) break; // Parent not found anywhere (e.g., SmrtObject)\n\n if (parentObj.decoratorConfig?.tableStrategy === 'sti') {\n return true; // Found STI ancestor\n }\n\n currentClass = this.parentRef(parentObj);\n }\n\n return false;\n }\n\n /**\n * Resolve a class name (simple `Content` or qualified `@pkg:Content`) to\n * the key it is stored under in `manifest.objects`, or `undefined` when the\n * manifest does not carry it. Manifest keys are qualified names; `extends`\n * and {@link findSTIBaseInfo} report simple names.\n */\n private resolveManifestKey(\n className: string,\n manifest: SmartObjectManifest,\n ): string | undefined {\n if (manifest.objects[className]) return className;\n const simpleName = className.includes(':')\n ? className.slice(className.lastIndexOf(':') + 1)\n : className;\n for (const [key, obj] of Object.entries(manifest.objects)) {\n if (obj.qualifiedName === className || obj.className === simpleName) {\n return key;\n }\n }\n return undefined;\n }\n\n /**\n * Find full STI base class info (className + tableName)\n *\n * Walks up the inheritance chain to find the STI base class and returns\n * both its className and tableName. This is critical for external STI bases\n * where the child needs to use the base's table name for schema generation.\n */\n private findSTIBaseInfo(\n obj: SmartObjectDefinition,\n manifest: SmartObjectManifest,\n ): { className: string; tableName: string } | undefined {\n if (!obj.extends) return undefined;\n\n // Build a lookup map for efficient access\n const objectsByName = new Map<string, SmartObjectDefinition>();\n for (const [_name, objDef] of Object.entries(manifest.objects)) {\n objectsByName.set(objDef.className, objDef);\n objectsByName.set(objDef.className.toLowerCase(), objDef);\n }\n\n // Track the oldest STI base found as we walk up\n // (we need to keep walking to find the ROOT STI class, not the first one)\n let stiBaseInfo: { className: string; tableName: string } | undefined;\n\n // Walk up the inheritance chain looking for the OLDEST STI base\n let currentClass: string | undefined = this.parentRef(obj);\n const visited = new Set<string>();\n\n while (currentClass) {\n if (visited.has(currentClass)) break;\n visited.add(currentClass);\n\n const parentObj = this.resolveParentDefinition(\n currentClass,\n obj,\n manifest,\n objectsByName,\n );\n\n if (!parentObj) break;\n\n if (parentObj.decoratorConfig?.tableStrategy === 'sti') {\n // Found an STI ancestor - it becomes the new candidate base\n // Keep walking to find the OLDEST/ROOT STI class in the hierarchy\n const tableName =\n parentObj.decoratorConfig?.tableName ||\n parentObj.schema?.tableName ||\n this.classNameToTableName(parentObj.className);\n stiBaseInfo = {\n className: parentObj.className,\n tableName,\n };\n }\n\n currentClass = this.parentRef(parentObj);\n }\n\n return stiBaseInfo; // Return the oldest STI ancestor found (or undefined if none)\n }\n\n /**\n * Convert class name to table name (snake_case pluralized)\n *\n * IMPORTANT: Must use the same algorithm as runtime's tableNameFromClass()\n * to ensure manifest-generated table names match runtime-derived names.\n */\n private classNameToTableName(className: string): string {\n // Use the shared pluralization function that handles English plurals correctly\n // (e.g., 'Currency' → 'currencies', 'JournalEntry' → 'journal_entries')\n return classnameToTablename(className);\n }\n\n private normalizeFrameworkInheritedField(\n ancestorName: string,\n fieldName: string,\n fieldDef: FieldDefinition,\n childClassName: string,\n ): FieldDefinition {\n if (\n this.simpleClassName(ancestorName) === 'SmrtHierarchical' &&\n fieldName === 'parentId'\n ) {\n return {\n ...fieldDef,\n type: 'foreignKey',\n related: childClassName,\n required: false,\n _meta: {\n ...(fieldDef._meta || {}),\n nullable: true,\n },\n };\n }\n\n return fieldDef;\n }\n\n private simpleClassName(className: string): string {\n return className.includes(':')\n ? className.split(':').pop() || className\n : className;\n }\n\n /**\n * Merge inherited fields into child classes (build-time inheritance resolution)\n *\n * For STI hierarchies, child classes don't define their own fields in source code\n * (they inherit from parent). This method merges parent fields into child manifests\n * so that runtime code doesn't need to do field resolution.\n *\n * Also handles collection classes (SmrtCollection<T>) that should inherit their\n * item class's tableName and collection when the item uses STI.\n *\n * Handles multi-level inheritance (grandparents, great-grandparents, etc.)\n * Automatically loads parent class definitions from external SMRT packages when needed\n *\n * @param manifest - The manifest to process in-place\n */\n public mergeInheritedFields(manifest: SmartObjectManifest): void {\n // Build a map of className -> objectDef for fast lookup\n const objectsByName = new Map<string, SmartObjectDefinition>();\n for (const [name, obj] of Object.entries(manifest.objects)) {\n objectsByName.set(obj.className, obj);\n // Also store by lowercase name for case-insensitive lookup\n objectsByName.set(obj.className.toLowerCase(), obj);\n }\n\n // FIRST PASS: Handle STI field merging and tableName inheritance\n // This must happen FIRST so that item classes (like Meeting) have their tableName\n // inherited from their STI base (like Event) before collection classes (like Meetings)\n // try to read it\n for (const obj of Object.values(manifest.objects)) {\n if (!obj.extends) continue; // No parent, skip\n\n // Always walk the chain below — fields and methods now have\n // independent merge rules (#2624):\n // FIELDS merge when ANY of:\n // (a) STI is in play — shared table with parent, full chain\n // merges.\n // (b) An ancestor in the chain is a framework abstract base class\n // (SmrtHierarchical, SmrtJunction, …) — those have no table of\n // their own, so structural fields they declare (e.g.\n // `SmrtHierarchical.parentId`) must propagate into every CTI\n // subclass's manifest, otherwise WHERE-clause validation\n // rejects queries against the inherited column.\n // For plain CTI through a user-defined base with its own table,\n // field merging is skipped per-ancestor below — each class keeps\n // its own table layout.\n // METHODS merge from every ancestor except framework base classes,\n // independent of STI/CTI — a concrete decorated ancestor's public\n // methods are real inherited API regardless of table strategy.\n // There is no early exit here for a \"plain CTI through a\n // user-defined base\" class: that is exactly the case whose\n // methods previously went unmerged (the under-report half of\n // #2624).\n const usesSTI = this.isSTIClass(obj, objectsByName, manifest);\n\n logger.debug(\n `[manifest-generator] Merging inherited fields for ${obj.className} from ${obj.extends}`,\n );\n\n // Build full inheritance chain (base -> child). Each ancestor keeps\n // the definition it resolved to: re-resolving its simple name later\n // could pick another package's same-named class (#4145).\n const inheritanceChain: string[] = [];\n const ancestorDefs: Array<SmartObjectDefinition | undefined> = [];\n let currentClass: string | undefined = this.parentRef(obj);\n const visited = new Set<string>();\n\n while (currentClass) {\n if (visited.has(currentClass)) {\n logger.warn(\n `[manifest-generator] Circular inheritance detected for ${obj.className}`,\n );\n break;\n }\n visited.add(currentClass);\n\n // Skips self-reference: when a local class has the same name as its\n // imported parent (e.g., local Performer extends external Performer),\n // the local lookup returns the child itself and falls through to the\n // external package lookup.\n const parentObj = this.resolveParentDefinition(\n currentClass,\n obj,\n manifest,\n objectsByName,\n );\n\n // Chain entries are simple names, as before; the resolved definition\n // rides alongside.\n const ancestorName = this.simpleClassName(currentClass);\n inheritanceChain.unshift(ancestorName); // Add to front (building base -> child)\n ancestorDefs.unshift(parentObj);\n if (!parentObj) break; // Parent not found anywhere (e.g., SmrtObject)\n currentClass = this.parentRef(parentObj);\n }\n\n logger.debug(\n `[manifest-generator] Inheritance chain for ${obj.className}: ${inheritanceChain.join(' -> ')}`,\n );\n\n // Merge fields from ancestors (base to child).\n //\n // STI path: pull in fields from every ancestor — they all share one\n // table.\n //\n // Non-STI (framework-base) path: pull in fields ONLY from framework\n // abstract bases (SmrtHierarchical, …). User-defined ancestors with\n // their own `@smrt()` decorator have their own tables in CTI, so\n // merging their columns onto a descendant would generate the wrong\n // schema.\n const mergedFields: Record<string, FieldDefinition> = {};\n const mergedFieldOwners = new Map<string, string>();\n const mergedMethods: Record<string, MethodDefinition> = {};\n\n for (const [index, ancestorName] of inheritanceChain.entries()) {\n const ancestor = ancestorDefs[index];\n if (!ancestor) continue;\n\n const ancestorIsFrameworkBase =\n FRAMEWORK_ABSTRACT_BASE_NAMES.has(ancestorName);\n\n // FIELDS: STI subclasses share one table, so every ancestor's\n // columns are needed. CTI subclasses pull fields only from framework\n // abstract bases — a concrete `@smrt()` ancestor has its own table,\n // so merging its columns here would generate the wrong schema.\n if (usesSTI || ancestorIsFrameworkBase) {\n // Keep the oldest concrete STI declaration, but let a concrete\n // class replace a framework abstract default. For example, Event\n // refines SmrtHierarchical.parentId with its relationship target\n // and an engine-scoped physical constraint. The local child's own\n // fields are still applied after this loop.\n for (const [fieldName, fieldDef] of Object.entries(ancestor.fields)) {\n const existingOwner = mergedFieldOwners.get(fieldName);\n const replacesFrameworkDefault =\n existingOwner !== undefined &&\n FRAMEWORK_ABSTRACT_BASE_NAMES.has(\n this.simpleClassName(existingOwner),\n ) &&\n !FRAMEWORK_ABSTRACT_BASE_NAMES.has(\n this.simpleClassName(ancestorName),\n );\n if (!existingOwner || replacesFrameworkDefault) {\n mergedFields[fieldName] = this.normalizeFrameworkInheritedField(\n ancestorName,\n fieldName,\n fieldDef,\n obj.className,\n );\n mergedFieldOwners.set(fieldName, ancestorName);\n }\n }\n }\n\n // METHODS (#2624): methods are not columns and never needed the\n // STI/CTI field rule above — they inherited it only by sharing the\n // loop. Give them their own rule instead: merge from every ancestor\n // except the universal object/collection primitives in\n // FRAMEWORK_METHOD_BASE_NAMES (see its doc comment — deliberately\n // narrower than FRAMEWORK_ABSTRACT_BASE_NAMES), independent of\n // `usesSTI`. This both stops STI subclasses from absorbing\n // `SmrtObject`/`SmrtClass`/`SmrtCollection` internals (over-merge)\n // and lets CTI subclasses inherit a concrete decorated ancestor's\n // own public methods (under-merge), matching the runtime resolver's\n // `getAllMethods()` — while still letting a framework abstract\n // base's own intended API (e.g. SmrtJunction.attach/detach,\n // SmrtHierarchical.getChildren) merge in, the same way its fields\n // already do.\n //\n // Assignment is unconditional (not \"first ancestor wins\"): the\n // outer loop walks `inheritanceChain` base-to-child, so a later\n // (more-derived) ancestor's override must replace an earlier one —\n // e.g. a middle class that overrides a grandparent method. This\n // matches the runtime resolver's own `getAllMethods()`, which\n // walks the same base-to-child order and does a plain `Map.set()`\n // per ancestor for the identical reason (see its \"Child methods\n // override parent methods (no merging)\" comment). The child's own\n // methods still win over everything via the unconditional\n // \"Add child's own methods\" step below.\n if (!FRAMEWORK_METHOD_BASE_NAMES.has(ancestorName)) {\n for (const [methodName, methodDef] of Object.entries(\n ancestor.methods || {},\n )) {\n mergedMethods[methodName] = methodDef;\n }\n }\n }\n\n // Add child's own fields (override any parent fields with same name)\n for (const [fieldName, fieldDef] of Object.entries(obj.fields)) {\n mergedFields[fieldName] = fieldDef;\n }\n\n // Add child's own methods\n for (const [methodName, methodDef] of Object.entries(obj.methods || {})) {\n mergedMethods[methodName] = methodDef;\n }\n\n // Update object definition with merged fields\n obj.fields = mergedFields;\n obj.methods = mergedMethods;\n\n // Share storage while allowing an explicit independent route collection.\n const stiBase = this.findSTIBase(obj, objectsByName, manifest);\n if (stiBase && stiBase !== obj) {\n // Determine the STI base's table name (explicit or derived from className)\n // Note: We don't use stiBase.collection as fallback because collection uses\n // lowercase-only format (e.g., 'querytestevents') while tableName needs\n // snake_case format (e.g., 'query_test_events')\n const baseTableName =\n stiBase.decoratorConfig?.tableName ||\n this.classNameToTableName(stiBase.className);\n\n if (\n (obj.decoratorConfig?.sensitive === true) !==\n (stiBase.decoratorConfig?.sensitive === true)\n ) {\n throw new ConfigurationError(\n `STI hierarchy ${stiBase.className} has mixed sensitivity; mark every class sensitive or use separate tables.`,\n 'CONFIG_STI_MIXED_SENSITIVITY',\n );\n }\n // Inherit tableName from STI base\n obj.decoratorConfig = obj.decoratorConfig || {};\n obj.decoratorConfig.tableName = baseTableName;\n logger.debug(\n `[manifest-generator] ${obj.className} inherits tableName: '${baseTableName}' from ${stiBase.className}`,\n );\n\n // Inherit tableStrategy from STI base (so runtime doesn't need to walk inheritance chain)\n if (stiBase.decoratorConfig?.tableStrategy) {\n obj.decoratorConfig.tableStrategy =\n stiBase.decoratorConfig.tableStrategy;\n logger.debug(\n `[manifest-generator] ${obj.className} inherits tableStrategy: '${stiBase.decoratorConfig.tableStrategy}' from ${stiBase.className}`,\n );\n }\n\n // Collection controls routes/permissions independently of shared storage.\n if (typeof obj.decoratorConfig.collection === 'string') {\n obj.collection = obj.decoratorConfig.collection;\n }\n // Preserve the inherited default when no collection was declared.\n if (\n !obj.decoratorConfig.collection &&\n stiBase.collection !== obj.collection\n ) {\n logger.debug(\n `[manifest-generator] ${obj.className} inherits collection: '${stiBase.collection}' from ${stiBase.className}`,\n );\n obj.collection = stiBase.collection;\n }\n }\n\n logger.debug(\n `[manifest-generator] ✅ ${obj.className} now has ${Object.keys(mergedFields).length} fields (including inherited)`,\n );\n }\n\n // A model subclass inherits every generated surface (and `sensitive`) it\n // leaves unset from its parent model. Before the collection pass below,\n // so a subclass's collection inherits the subclass's effective surface.\n this.applySubclassExposureInheritance(manifest, objectsByName);\n\n // SECOND PASS: Handle collection classes that should inherit from their item class\n // This must happen AFTER STI field merging so item classes have their tableName set\n for (const obj of Object.values(manifest.objects)) {\n // Check if this is a collection class (extends SmrtCollection)\n const isCollection =\n obj.extends === 'SmrtCollection' ||\n this.extendsCollection(obj, objectsByName);\n // Junction and report collections inherit their model's exposure too,\n // but keep their own storage naming (that predates this pass).\n if (!isCollection && !this.extendsAnyCollectionBase(obj, objectsByName)) {\n continue;\n }\n\n // Find the item class from _itemClass static property\n const itemClass = this.findItemClass(obj, manifest, objectsByName);\n if (!itemClass || itemClass === obj) continue;\n\n logger.debug(\n `[manifest-generator] ${obj.className} is a collection class for ${itemClass.className}`,\n );\n\n if (isCollection) {\n // Inherit tableName from item class (which may have inherited it from STI base)\n if (itemClass.decoratorConfig?.tableName) {\n obj.decoratorConfig = obj.decoratorConfig || {};\n obj.decoratorConfig.tableName = itemClass.decoratorConfig.tableName;\n logger.debug(\n `[manifest-generator] ${obj.className} inherits tableName: '${itemClass.decoratorConfig.tableName}' from item class ${itemClass.className}`,\n );\n }\n\n // Routes may use an explicit namespace independently of item storage.\n // Match registry registration, where decorator collection wins.\n if (typeof obj.decoratorConfig?.collection === 'string') {\n obj.collection = obj.decoratorConfig.collection;\n } else if (itemClass.collection !== obj.collection) {\n logger.debug(\n `[manifest-generator] ${obj.className} inherits collection: '${itemClass.collection}' from item class ${itemClass.className} (was '${obj.collection}')`,\n );\n obj.collection = itemClass.collection;\n }\n }\n\n // A collection class is generated as a resource of its own, so a\n // surface it leaves unset inherits its model's exposure: `false`,\n // the CRUD verbs of an `include` list, an `exclude` list, and\n // read-only MCP over a `sensitive` model. Without this an object-form\n // model config left the collection open on every transport. From an\n // `include` list only CRUD verbs and names only the collection declares\n // carry over: a name the model declares is the model's own method, and\n // a same-named collection method is a different operation, so it stays\n // closed until the collection lists it. See `registry/collection-exposure.ts`.\n const inherited = inheritCollectionExposure(\n obj.decoratorConfig || {},\n itemClass.decoratorConfig || {},\n {\n collection: new Set(Object.keys(obj.methods || {})),\n item: new Set(Object.keys(itemClass.methods || {})),\n },\n );\n if (Object.keys(inherited).length > 0) {\n obj.decoratorConfig = { ...(obj.decoratorConfig || {}), ...inherited };\n logger.debug(\n `[manifest-generator] ${obj.className} inherits ${Object.keys(inherited).join(', ')} exposure from item class ${itemClass.className}`,\n );\n }\n }\n }\n\n /**\n * The model a model class directly extends, from this manifest or an\n * external SMRT dependency's, or `undefined` when its parent is a framework\n * base, a collection or unknown, or when the class is itself a collection.\n */\n private findParentModel(\n obj: SmartObjectDefinition,\n manifest: SmartObjectManifest,\n objectsByName: Map<string, SmartObjectDefinition>,\n ): SmartObjectDefinition | undefined {\n const parentName = obj.extendsQualified || obj.extends;\n if (!parentName) return undefined;\n const simpleParent = this.simpleClassName(parentName);\n if (\n FRAMEWORK_ABSTRACT_BASE_NAMES.has(simpleParent) ||\n FRAMEWORK_METHOD_BASE_NAMES.has(simpleParent) ||\n isSmrtCollectionExtendsName(parentName)\n ) {\n return undefined;\n }\n if (\n this.extendsCollection(obj, objectsByName) ||\n this.extendsAnyCollectionBase(obj, objectsByName)\n ) {\n return undefined;\n }\n let parent =\n (obj.extendsQualified\n ? (manifest.objects[obj.extendsQualified] as\n | SmartObjectDefinition\n | undefined)\n : undefined) ?? objectsByName.get(obj.extends ?? simpleParent);\n if (parent === obj) parent = undefined;\n if (!parent && manifest.smrtDependencies?.length) {\n parent = this.loadParentFromExternalPackage(\n parentName,\n manifest.smrtDependencies,\n objectsByName,\n );\n }\n if (!parent || parent === obj) return undefined;\n if (\n this.extendsCollection(parent, objectsByName) ||\n this.extendsAnyCollectionBase(parent, objectsByName)\n ) {\n return undefined;\n }\n return parent;\n }\n\n /**\n * A model's config with the surfaces it inherits from its ancestors\n * (`registry/subclass-exposure.ts`), computed without mutating `obj` or any\n * external manifest entry.\n */\n private subclassEffectiveConfig(\n obj: SmartObjectDefinition,\n manifest: SmartObjectManifest,\n objectsByName: Map<string, SmartObjectDefinition>,\n memo: Map<SmartObjectDefinition, SmartObjectConfig>,\n visiting: Set<SmartObjectDefinition> = new Set(),\n ): SmartObjectConfig {\n const cached = memo.get(obj);\n if (cached) return cached;\n const own = obj.decoratorConfig || {};\n if (visiting.has(obj)) return own;\n visiting.add(obj);\n let config = own;\n const parent = this.findParentModel(obj, manifest, objectsByName);\n if (parent) {\n const inherited = inheritSubclassExposure(\n own,\n this.subclassEffectiveConfig(\n parent,\n manifest,\n objectsByName,\n memo,\n visiting,\n ),\n );\n if (Object.keys(inherited).length > 0) config = { ...own, ...inherited };\n }\n visiting.delete(obj);\n memo.set(obj, config);\n return config;\n }\n\n /**\n * Give every model subclass in this manifest the generated surfaces and\n * `sensitive` flag it leaves unset from its parent model. Without this an\n * STI child such as `Person extends Profile` was generated with the open\n * default surface, publishing every write and method `Profile` closes.\n */\n private applySubclassExposureInheritance(\n manifest: SmartObjectManifest,\n objectsByName: Map<string, SmartObjectDefinition>,\n ): void {\n const memo = new Map<SmartObjectDefinition, SmartObjectConfig>();\n const updates: Array<[SmartObjectDefinition, SmartObjectConfig]> = [];\n for (const obj of Object.values(manifest.objects)) {\n const effective = this.subclassEffectiveConfig(\n obj,\n manifest,\n objectsByName,\n memo,\n );\n if (effective !== (obj.decoratorConfig || {})) {\n updates.push([obj, effective]);\n }\n }\n for (const [obj, effective] of updates) {\n obj.decoratorConfig = effective;\n logger.debug(\n `[manifest-generator] ${obj.className} inherits generated-surface exposure from ${obj.extends}`,\n );\n }\n }\n\n /**\n * Fail the build when a model subclass's own `@smrt()` opens a generated\n * operation (a CRUD verb or a parent method, on REST, MCP or CLI) that its\n * parent model closes, or drops its parent's `sensitive: true`, without\n * naming it in `widenParentExposure`. Runs after inheritance, so only a\n * subclass's own config can trip it.\n */\n private assertSubclassExposure(manifest: SmartObjectManifest): void {\n const objectsByName = new Map<string, SmartObjectDefinition>();\n for (const objectDef of Object.values(manifest.objects)) {\n objectsByName.set(objectDef.className, objectDef);\n }\n const memo = new Map<SmartObjectDefinition, SmartObjectConfig>();\n const findings: Parameters<typeof formatSubclassExposureEscalations>[0] =\n [];\n for (const obj of Object.values(manifest.objects)) {\n const parent = this.findParentModel(obj, manifest, objectsByName);\n if (!parent) continue;\n const childConfig = this.subclassEffectiveConfig(\n obj,\n manifest,\n objectsByName,\n memo,\n );\n const parentConfig = this.subclassEffectiveConfig(\n parent,\n manifest,\n objectsByName,\n memo,\n );\n const parentOperations = Object.entries(parent.methods || {})\n .filter(([, method]) => method.isPublic !== false)\n .map(([name]) => name);\n const escalations = findSubclassExposureEscalations(\n childConfig,\n parentConfig,\n parentOperations,\n );\n const stale = findStaleWidenings(childConfig, parentConfig);\n if (escalations.length > 0 || stale.length > 0) {\n findings.push({\n subclass: obj.qualifiedName || obj.className,\n parent: parent.qualifiedName || parent.className,\n escalations,\n stale,\n });\n }\n }\n if (findings.length > 0) {\n throw new ConfigurationError(\n formatSubclassExposureEscalations(findings),\n 'CONFIG_SUBCLASS_EXPOSURE',\n );\n }\n }\n\n /**\n * Fail the build when a collection class opens a generated CRUD write (MCP\n * or CLI) that its model keeps closed. Runs after inheritance, so only a\n * collection's own `@smrt()` surface can trip it.\n */\n private assertCollectionExposure(manifest: SmartObjectManifest): void {\n const objectsByName = new Map(\n Object.values(manifest.objects).map((objectDef) => [\n objectDef.className,\n objectDef,\n ]),\n );\n const findings: Parameters<typeof formatCollectionWriteEscalations>[0] = [];\n for (const obj of Object.values(manifest.objects)) {\n if (\n obj.extends !== 'SmrtCollection' &&\n !this.extendsCollection(obj, objectsByName) &&\n !this.extendsAnyCollectionBase(obj, objectsByName)\n ) {\n continue;\n }\n const itemClass = this.findItemClass(obj, manifest, objectsByName);\n if (!itemClass || itemClass === obj) continue;\n const escalations = findCollectionWriteEscalations(\n obj.decoratorConfig || {},\n itemClass.decoratorConfig || {},\n );\n if (escalations.length > 0) {\n findings.push({\n collection: obj.qualifiedName || obj.className,\n model: itemClass.qualifiedName || itemClass.className,\n escalations,\n });\n }\n }\n if (findings.length > 0) {\n throw new ConfigurationError(\n formatCollectionWriteEscalations(findings),\n 'CONFIG_COLLECTION_EXPOSURE',\n );\n }\n }\n\n /**\n * Whether a class descends from any SMRT collection base (`SmrtCollection`,\n * `SmrtJunction`, `SmrtJunctionBase`, `SmrtReportCollection`), following\n * parents declared in this manifest.\n */\n private extendsAnyCollectionBase(\n obj: SmartObjectDefinition,\n objectsByName: Map<string, SmartObjectDefinition>,\n ): boolean {\n let current: SmartObjectDefinition | undefined = obj;\n const visited = new Set<string>();\n while (current?.extends) {\n if (isSmrtCollectionExtendsName(current.extends)) return true;\n if (visited.has(current.extends)) return false;\n visited.add(current.extends);\n current = objectsByName.get(current.extends);\n }\n return false;\n }\n\n /**\n * Check if a class extends SmrtCollection (directly or indirectly)\n *\n * @param obj - The object definition to check\n * @param objectsByName - Map of className -> objectDef for lookups\n * @returns true if this class extends SmrtCollection\n */\n private extendsCollection(\n obj: SmartObjectDefinition,\n objectsByName: Map<string, SmartObjectDefinition>,\n ): boolean {\n if (!obj.extends) return false;\n\n // Walk up inheritance chain looking for SmrtCollection\n let currentClass: string | undefined = obj.extends;\n const visited = new Set<string>();\n\n while (currentClass) {\n if (visited.has(currentClass)) break;\n visited.add(currentClass);\n\n if (currentClass === 'SmrtCollection') return true;\n\n const parentObj = objectsByName.get(currentClass);\n if (!parentObj) break;\n\n currentClass = parentObj.extends;\n }\n\n return false;\n }\n\n /**\n * Find the item class for a collection class\n *\n * Lookup priority:\n * 1. extendsTypeArg - Generic type argument from extends clause (e.g., \"Meeting\" from SmrtCollection<Meeting>)\n * 2. _itemClass static property - May be captured by AST scanner\n * 3. Name-based inference - Fallback (e.g., \"Meetings\" -> \"Meeting\")\n *\n * @param collectionObj - The collection class definition\n * @param manifest - The manifest\n * @param objectsByName - Map of className -> objectDef for lookups\n * @returns Item class definition or undefined\n */\n private findItemClass(\n collectionObj: SmartObjectDefinition,\n manifest: SmartObjectManifest,\n objectsByName: Map<string, SmartObjectDefinition>,\n ): SmartObjectDefinition | undefined {\n // PRIORITY 1: Use generic type argument from extends clause\n // This is the most reliable method: SmrtCollection<Meeting> -> \"Meeting\"\n if (collectionObj.extendsTypeArg) {\n const itemClassName = collectionObj.extendsTypeArg;\n logger.debug(\n `[manifest-generator] ${collectionObj.className} has extendsTypeArg: ${itemClassName}`,\n );\n\n // Try to find the item class by name in local manifest\n const itemClass = objectsByName.get(itemClassName);\n if (itemClass) {\n logger.debug(\n `[manifest-generator] Found item class ${itemClassName} in local manifest`,\n );\n return itemClass;\n }\n\n // Try loading from external packages\n if (manifest.smrtDependencies && manifest.smrtDependencies.length > 0) {\n const externalItemClass = this.loadParentFromExternalPackage(\n itemClassName,\n manifest.smrtDependencies,\n objectsByName,\n );\n if (externalItemClass) {\n logger.debug(\n `[manifest-generator] Found item class ${itemClassName} in external package`,\n );\n return externalItemClass;\n }\n }\n }\n\n // PRIORITY 2: Look for _itemClass static field in the collection class\n // This is defined like: static readonly _itemClass = Meeting;\n // Note: AST scanner currently skips static properties, so this rarely works\n const itemClassField = collectionObj.fields._itemClass;\n\n if (itemClassField) {\n // Extract class name from the field's default value or metadata\n // The AST scanner might capture this as a reference\n const itemClassName = itemClassField.related || itemClassField.default;\n\n if (itemClassName && typeof itemClassName === 'string') {\n // Try to find the item class by name\n const itemClass = objectsByName.get(itemClassName);\n if (itemClass) {\n return itemClass;\n }\n\n // Try loading from external packages\n if (manifest.smrtDependencies && manifest.smrtDependencies.length > 0) {\n return this.loadParentFromExternalPackage(\n itemClassName,\n manifest.smrtDependencies,\n objectsByName,\n );\n }\n }\n }\n\n // PRIORITY 3: Fallback - Try to infer from collection class name\n // Generate candidate item class names and check if they exist\n const collectionName = collectionObj.className;\n const candidates: string[] = [];\n\n // Strip \"Collection\" suffix first if present\n let baseName = collectionName;\n if (baseName.endsWith('Collection')) {\n baseName = baseName.slice(0, -'Collection'.length);\n }\n\n // Generate singularization candidates (order matters - try most specific first)\n // 1. Exact name (e.g., \"Event\" from \"EventCollection\")\n candidates.push(baseName);\n\n // 2. Remove trailing 's' (e.g., \"Meetings\" -> \"Meeting\")\n if (baseName.endsWith('s') && baseName.length > 1) {\n candidates.push(baseName.slice(0, -1));\n }\n\n // 3. Handle 'ies' -> 'y' (e.g., \"Categories\" -> \"Category\")\n if (baseName.endsWith('ies') && baseName.length > 3) {\n candidates.push(`${baseName.slice(0, -3)}y`);\n }\n\n // 4. Handle 'es' -> '' for words ending in s/x/z/ch/sh (e.g., \"Statuses\" -> \"Status\")\n if (baseName.endsWith('es') && baseName.length > 2) {\n candidates.push(baseName.slice(0, -2));\n }\n\n // Try each candidate against local classes first, then external packages\n // Skip candidates that match the collection class itself\n for (const candidate of candidates) {\n if (candidate === collectionObj.className) continue; // Don't match self\n const itemClass = objectsByName.get(candidate);\n if (itemClass) {\n return itemClass;\n }\n }\n\n // Try loading from external packages\n if (manifest.smrtDependencies && manifest.smrtDependencies.length > 0) {\n for (const candidate of candidates) {\n if (candidate === collectionObj.className) continue; // Don't match self\n const itemClass = this.loadParentFromExternalPackage(\n candidate,\n manifest.smrtDependencies,\n objectsByName,\n );\n if (itemClass) {\n return itemClass;\n }\n }\n }\n\n return undefined;\n }\n\n /**\n * Check if a class uses STI (either explicitly or inherited from an ancestor)\n *\n * Walks up the inheritance chain to find if any ancestor has tableStrategy: 'sti'.\n * If found, all descendants inherit STI and should have fields merged.\n * Also checks external SMRT packages for parent class definitions.\n *\n * @param obj - The object definition to check\n * @param objectsByName - Map of className -> objectDef for lookups\n * @param manifest - The manifest (for accessing smrtDependencies)\n * @returns true if this class uses STI (directly or inherited)\n */\n private isSTIClass(\n obj: SmartObjectDefinition,\n objectsByName: Map<string, SmartObjectDefinition>,\n manifest: SmartObjectManifest,\n ): boolean {\n // Check if explicitly marked as STI\n if (obj.decoratorConfig?.tableStrategy === 'sti') {\n return true;\n }\n\n // Walk up the inheritance chain looking for STI base\n let currentClass: string | undefined = this.parentRef(obj);\n const visited = new Set<string>();\n\n while (currentClass) {\n if (visited.has(currentClass)) {\n break; // Circular inheritance, stop\n }\n visited.add(currentClass);\n\n // Skips self-reference (local class with same name as imported parent).\n const parentDef = this.resolveParentDefinition(\n currentClass,\n obj,\n manifest,\n objectsByName,\n );\n\n if (!parentDef) break; // Parent not found anywhere\n\n // Check if this ancestor uses STI\n if (parentDef.decoratorConfig?.tableStrategy === 'sti') {\n return true; // Found STI ancestor\n }\n\n currentClass = this.parentRef(parentDef);\n }\n\n return false; // No STI in hierarchy\n }\n\n /**\n * Find the STI base class for a given object\n *\n * Walks up the inheritance chain to find the first ancestor that defines\n * tableStrategy: 'sti'. This is the class that owns the shared table.\n *\n * @param obj - The object definition to find the STI base for\n * @param objectsByName - Map of className -> objectDef for lookups\n * @param manifest - The manifest (for accessing smrtDependencies)\n * @returns The STI base class definition, or the object itself if it's the base\n */\n private findSTIBase(\n obj: SmartObjectDefinition,\n objectsByName: Map<string, SmartObjectDefinition>,\n manifest: SmartObjectManifest,\n ): SmartObjectDefinition | undefined {\n // Track the oldest STI class found as we walk up\n let stiBase: SmartObjectDefinition | undefined;\n\n // If this object explicitly defines STI, it's a candidate (but ancestors may also be STI)\n if (obj.decoratorConfig?.tableStrategy === 'sti') {\n stiBase = obj;\n }\n\n // Walk up the inheritance chain looking for the oldest STI base\n let currentClass: string | undefined = this.parentRef(obj);\n const visited = new Set<string>();\n\n while (currentClass) {\n if (visited.has(currentClass)) {\n break; // Circular inheritance, stop\n }\n visited.add(currentClass);\n\n // Skips self-reference (local class with same name as imported parent).\n const parentDef = this.resolveParentDefinition(\n currentClass,\n obj,\n manifest,\n objectsByName,\n );\n\n if (!parentDef) break; // Parent not found anywhere\n\n // Check if this ancestor defines STI - if so, it becomes the new candidate base\n // (we keep walking to find the oldest/root STI class)\n if (parentDef.decoratorConfig?.tableStrategy === 'sti') {\n stiBase = parentDef;\n }\n\n currentClass = this.parentRef(parentDef);\n }\n\n return stiBase; // Return the oldest STI ancestor found (or undefined if none)\n }\n\n /**\n * Load parent class definition from external SMRT packages\n *\n * When a child class extends a parent from an external package (e.g., praeco's Council extends\n * smrt-profiles' Organization), this method loads the parent's manifest and extracts the\n * parent's field definitions.\n *\n * @param parentClassName - Name of the parent class to find\n * @param smrtDependencies - List of external SMRT packages to search\n * @param objectsByName - Map to cache loaded external objects\n * @returns Parent object definition if found, undefined otherwise\n */\n private loadParentFromExternalPackage(\n parentClassName: string,\n smrtDependencies: string[],\n objectsByName: Map<string, SmartObjectDefinition>,\n ): SmartObjectDefinition | undefined {\n // Try each external SMRT dependency\n for (const packageName of smrtDependencies) {\n const externalManifest = loadExternalManifestSync(packageName);\n\n if (!externalManifest) {\n continue;\n }\n\n // Use lookupInManifest for O(1) lookup via cached className index\n // Handles both qualified names and simple class names\n const parentObj = lookupInManifest(externalManifest, parentClassName);\n\n if (parentObj) {\n // Cache the loaded parent object for future lookups, but never over\n // a local class of the same simple name: that entry is this\n // package's own parent for its other subclasses (#4145).\n if (!objectsByName.has(parentObj.className)) {\n objectsByName.set(parentObj.className, parentObj);\n }\n if (!objectsByName.has(parentObj.className.toLowerCase())) {\n objectsByName.set(parentObj.className.toLowerCase(), parentObj);\n }\n\n return parentObj;\n }\n }\n\n return undefined;\n }\n\n /**\n * Determine import path from package.json exports\n *\n * Tries the following strategies in order:\n * 1. package.json exports[\"./objects\"] - Specific objects export\n * 2. package.json exports[\".\"] - Main export\n * 3. package.json main - Main field\n * 4. Fallback to package name\n */\n /**\n * Determine the specifier consumers should import an object from.\n *\n * `filePath` was accepted (and ignored — the parameter was named\n * `_filePath`) since before this fix, so every object always resolved to\n * the bare package name regardless of where it actually lived. That is\n * wrong for an object scanned from a file only a non-root `exports`\n * subpath serves (e.g. `./server`): the manifest advertised the object as\n * importable from the package root, but the root bundle never exports it,\n * so a consumer dynamically importing by manifest metadata (or generating\n * `.smrt/register.js`, `consumer-plugin/index.ts`'s own\n * `determineImportPath`) silently failed to find it. That is smrt#2845 —\n * `DataSurfaceActionIdempotencyState` in `@happyvertical/smrt-agents` lives\n * under `src/server/` (served only by the `./server` export), but the\n * manifest pointed consumers at the bare `@happyvertical/smrt-agents`\n * specifier.\n *\n * Strategy: match `filePath` against the package's `exports` subpaths —\n * `src/<segment>/...` or `src/<segment>.ts` maps to the `./<segment>`\n * export key — and prefer the longest matching segment. Falls back to the\n * legacy behavior (bare package name, with the `./objects` special case)\n * when the file does not match any subpath, which covers objects reachable\n * from the root `.` entry point.\n */\n private determineImportPath(\n packageJson: PackageJsonLike,\n filePath?: string,\n ): string {\n // Only invoked once a package name is known (guarded at the call site),\n // so `name` is always present here.\n const packageName = packageJson.name as string;\n\n if (packageJson.exports && typeof packageJson.exports === 'object') {\n const subpathSegment = this.matchExportsSubpath(\n packageJson.exports,\n filePath,\n );\n if (subpathSegment) {\n return `${packageName}/${subpathSegment}`;\n }\n\n // Legacy special case, kept for packages whose `./objects` export\n // predates file-path-based matching and whose objects' `filePath`\n // does not follow the `src/objects/...` convention above.\n if (packageJson.exports['./objects']) {\n return `${packageName}/objects`;\n }\n }\n\n // Strategy 2/3: main field or bare fallback — both resolve to the\n // package root, which is where an unmatched object is assumed to live.\n return packageName;\n }\n\n /**\n * Match a scanned object's `filePath` against a package's `exports` map,\n * returning the longest matching non-root subpath segment (e.g. `\"server\"`\n * for `./server`), or `undefined` when the file does not correspond to any\n * declared subpath (the object is assumed reachable from the root `.`\n * entry point instead).\n */\n private matchExportsSubpath(\n exportsMap: Record<string, unknown>,\n filePath?: string,\n ): string | undefined {\n if (!filePath) return undefined;\n\n const normalized = filePath.replace(/\\\\/g, '/');\n const srcMarker = 'src/';\n const srcIndex = normalized.lastIndexOf(srcMarker);\n if (srcIndex === -1) return undefined;\n const relativeToSrc = normalized.slice(srcIndex + srcMarker.length);\n\n // Path components with any source-file extension stripped from the last\n // one, so `lib/models/Category.ts` and `server.js` both compare as plain\n // component lists (`['lib','models','Category']`, `['server']`).\n const pathParts = relativeToSrc.split('/');\n const lastIndex = pathParts.length - 1;\n pathParts[lastIndex] = pathParts[lastIndex].replace(\n /\\.(ts|tsx|js|jsx|mjs|cjs)$/,\n '',\n );\n\n const segments = Object.keys(exportsMap)\n .filter(\n (key) =>\n key !== '.' &&\n key !== './package.json' &&\n !key.includes('*') &&\n // Exclude subpaths that resolve to a non-JS asset (e.g. the\n // `./manifest`/`./manifest.json` convention pointing at\n // `dist/manifest.json`). No @smrt object's source file can ever\n // legitimately resolve there, so this only guards against a\n // coincidental `src/manifest/...` path being misattributed to it.\n !targetsJsonAsset(exportsMap[key]),\n )\n .map((key) => key.replace(/^\\.\\//, ''))\n .filter((segment) => segment.length > 0)\n // Longest first so a nested segment (rare) wins over a shorter prefix.\n .sort((a, b) => b.length - a.length);\n\n return segments.find((segment) => {\n const segmentParts = segment.split('/');\n // Match the segment's components as a contiguous run anywhere in the\n // file's path — not just a root-level prefix. Handles both a direct\n // subpath directory (`server/x.ts` for `./server`) and a re-export\n // barrel whose real source lives deeper than its export key implies\n // (`@happyvertical/smrt-products`: `./models` -> `src/models.ts` ->\n // `export * from './lib/models/index'`, with the actual `@smrt()`\n // classes scanned from `src/lib/models/*.ts` — `relativeToSrc` is\n // `lib/models/Category.ts`, which contains `models` as a component,\n // just not at index 0).\n for (\n let start = 0;\n start <= pathParts.length - segmentParts.length;\n start++\n ) {\n if (\n segmentParts.every(\n (part, offset) => pathParts[start + offset] === part,\n )\n ) {\n return true;\n }\n }\n return false;\n });\n }\n\n /**\n * Generate TypeScript interfaces from manifest\n */\n generateTypeDefinitions(manifest: SmartObjectManifest): string {\n const interfaces: string[] = [];\n\n // Manifest key order follows scan/discovery order, which is not stable\n // across runs (#2749): the vite-plugin's server-mode `@smrt/types`\n // resolution calls this method directly, so sort deterministically\n // before emitting for the same reason as the prebuild/client-mode paths.\n const sortedEntries = Object.entries(manifest.objects).sort(\n ([leftKey, left], [rightKey, right]) =>\n compareText(\n left.qualifiedName || leftKey,\n right.qualifiedName || rightKey,\n ) || compareText(leftKey, rightKey),\n );\n for (const [_name, obj] of sortedEntries) {\n interfaces.push(this.generateInterface(obj));\n }\n\n return interfaces.join('\\n\\n');\n }\n\n /**\n * Generate a single interface definition\n */\n private generateInterface(obj: SmartObjectDefinition): string {\n const fields = Object.entries(obj.fields)\n .map(([name, field]) => {\n const optional = !field.required ? '?' : '';\n const type = this.mapFieldTypeToTS(field.type);\n return ` ${name}${optional}: ${type};`;\n })\n .join('\\n');\n\n return `export interface ${obj.className}Data {\n${fields}\n}`;\n }\n\n /**\n * Map field types to TypeScript types\n */\n private mapFieldTypeToTS(fieldType: string): string {\n switch (fieldType) {\n case 'text':\n return 'string';\n case 'decimal':\n return 'number';\n case 'integer':\n return 'number';\n case 'boolean':\n return 'boolean';\n case 'datetime':\n return 'Date | string';\n case 'json':\n return 'any';\n case 'foreignKey':\n return 'string';\n case 'crossPackageRef':\n return 'string';\n default:\n return 'any';\n }\n }\n\n /**\n * Generate simple endpoint list for testing/documentation\n */\n generateRestEndpoints(manifest: SmartObjectManifest): string {\n const endpoints: string[] = [];\n\n for (const [_name, obj] of Object.entries(manifest.objects)) {\n const apiConfig = obj.decoratorConfig.api;\n if (apiConfig !== false) {\n endpoints.push(...this.getSimpleEndpoints(obj, manifest));\n }\n }\n\n return endpoints.join('\\n');\n }\n\n /**\n * Generate REST endpoint code implementations\n */\n generateRestEndpointCode(manifest: SmartObjectManifest): string {\n const endpoints: string[] = [];\n\n for (const [_name, obj] of Object.entries(manifest.objects)) {\n const apiConfig = obj.decoratorConfig.api;\n if (apiConfig !== false) {\n endpoints.push(this.generateRestEndpoint(obj));\n }\n }\n\n return endpoints.join('\\n\\n');\n }\n\n /**\n * Get simple endpoint strings for an object\n */\n private getApiRouteMetadata(\n obj: SmartObjectDefinition,\n actionName: string,\n actionDef: MethodDefinition | { isStatic?: boolean },\n ): {\n scope: 'item' | 'collection';\n method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n path: string;\n } {\n const config =\n obj.decoratorConfig.api && typeof obj.decoratorConfig.api === 'object'\n ? obj.decoratorConfig.api\n : undefined;\n // `@method({ httpMethod, path })` wins field by field over the class-level\n // `api.routes[action]` entry, the same merge `resolveApiActionRouteConfig`\n // and the knowledge artifact perform. Reading `routes` alone printed the\n // PRE-migration verb and path for a class that had moved to the decorator\n // (#2686).\n const effective = resolveEffectiveActionMetadata({\n actionName,\n method: actionDef,\n apiConfig: config,\n });\n const normalizedPath = (effective.path || actionName)\n .split('/')\n .map((segment) => segment.trim())\n .filter(Boolean)\n .join('/');\n const isCollectionClass =\n obj.extends === 'SmrtCollection' || !!obj.extendsTypeArg;\n\n const defaultScope =\n isCollectionClass || actionDef.isStatic ? 'collection' : 'item';\n\n return {\n scope: resolveCustomActionMetadata({\n actionName,\n method: actionDef,\n apiConfig: config,\n defaultScope,\n }).scope,\n method: effective.httpMethod ?? 'POST',\n path: normalizedPath || actionName,\n };\n }\n\n private getSimpleEndpoints(\n obj: SmartObjectDefinition,\n manifest?: SmartObjectManifest,\n ): string[] {\n const { collection } = obj;\n const config = obj.decoratorConfig.api;\n const exclude = (typeof config === 'object' && config?.exclude) || [];\n const include =\n (typeof config === 'object' && config?.include) || undefined;\n const isCollectionClass =\n obj.extends === 'SmrtCollection' || !!obj.extendsTypeArg;\n const isModelClassName = createManifestClassNamePredicate(manifest);\n\n const endpoints: string[] = [];\n\n // Determine which operations to include\n const shouldInclude = (op: string) => {\n if (include && !include.includes(op)) return false;\n if (exclude.includes(op)) return false;\n return true;\n };\n\n if (!isCollectionClass) {\n if (shouldInclude('list')) {\n endpoints.push(`GET /${collection}`);\n }\n if (shouldInclude('create')) {\n endpoints.push(`POST /${collection}`);\n }\n if (shouldInclude('get')) {\n endpoints.push(`GET /${collection}/:id`);\n }\n if (shouldInclude('update')) {\n endpoints.push(`PUT /${collection}/:id`);\n }\n if (shouldInclude('delete')) {\n endpoints.push(`DELETE /${collection}/:id`);\n }\n }\n\n // Custom actions read the ONE shared exposure resolver rather than a local\n // copy of the include/exclude rule. This listing is a published virtual\n // module (`@happyvertical/smrt-virt-routes`), so a stale rule here\n // advertises operations whose routes the emitters never wrote -- exactly\n // the consumer disagreement #2686 exists to close.\n for (const [actionName, actionDef] of Object.entries(obj.methods)) {\n if (\n !resolveApiMethodExposure({\n actionName,\n method: actionDef,\n apiConfig: config,\n isCollectionClass,\n ...(isModelClassName ? { isModelClassName } : {}),\n }).exposed\n ) {\n continue;\n }\n\n const route = this.getApiRouteMetadata(obj, actionName, actionDef);\n const suffix = route.scope === 'collection' ? '' : '/:id';\n endpoints.push(`${route.method} /${collection}${suffix}/${route.path}`);\n }\n\n return endpoints;\n }\n\n /**\n * Generate a single REST endpoint\n */\n private generateRestEndpoint(obj: SmartObjectDefinition): string {\n const { collection, className } = obj;\n const config = obj.decoratorConfig.api;\n const exclude = (typeof config === 'object' && config?.exclude) || [];\n const include =\n (typeof config === 'object' && config?.include) || undefined;\n\n const operations: string[] = [];\n\n // Determine which operations to include\n const shouldInclude = (op: string) => {\n if (include && !include.includes(op)) return false;\n if (exclude.includes(op)) return false;\n return true;\n };\n\n if (shouldInclude('list')) {\n operations.push(` // GET /${collection} - List ${collection}`);\n operations.push(` app.get('/${collection}', async (req: Request) => {`);\n operations.push(\n ` const collection = await get${className}Collection();`,\n );\n operations.push(' const items = await collection.list(req.query);');\n operations.push(' return Response.json(items);');\n operations.push(' });');\n }\n\n if (shouldInclude('get')) {\n operations.push(` // GET /${collection}/:id - Get ${className}`);\n operations.push(\n ` app.get('/${collection}/:id', async (req: Request) => {`,\n );\n operations.push(\n ` const collection = await get${className}Collection();`,\n );\n operations.push(' const item = await collection.get(req.params.id);');\n operations.push(\n ` if (!item) return new Response('Not found', { status: 404 });`,\n );\n operations.push(' return Response.json(item);');\n operations.push(' });');\n }\n\n if (shouldInclude('create')) {\n operations.push(` // POST /${collection} - Create ${className}`);\n operations.push(` app.post('/${collection}', async (req: Request) => {`);\n operations.push(\n ` const collection = await get${className}Collection();`,\n );\n operations.push(' const data = await req.json();');\n operations.push(' const item = await collection.create(data);');\n operations.push(' return Response.json(item, { status: 201 });');\n operations.push(' });');\n }\n\n if (shouldInclude('update')) {\n operations.push(` // PUT /${collection}/:id - Update ${className}`);\n operations.push(\n ` app.put('/${collection}/:id', async (req: Request) => {`,\n );\n operations.push(\n ` const collection = await get${className}Collection();`,\n );\n operations.push(' const data = await req.json();');\n operations.push(\n ' const item = await collection.update(req.params.id, data);',\n );\n operations.push(\n ` if (!item) return new Response('Not found', { status: 404 });`,\n );\n operations.push(' return Response.json(item);');\n operations.push(' });');\n }\n\n if (shouldInclude('delete')) {\n operations.push(` // DELETE /${collection}/:id - Delete ${className}`);\n operations.push(\n ` app.delete('/${collection}/:id', async (req: Request) => {`,\n );\n operations.push(\n ` const collection = await get${className}Collection();`,\n );\n operations.push(\n ' const success = await collection.delete(req.params.id);',\n );\n operations.push(\n ` if (!success) return new Response('Not found', { status: 404 });`,\n );\n operations.push(` return new Response('', { status: 204 });`);\n operations.push(' });');\n }\n\n return `// ${className} endpoints\\n${operations.join('\\n')}`;\n }\n\n /**\n * Generate simple MCP tool names for testing/documentation\n */\n generateMCPTools(manifest: SmartObjectManifest): string {\n const tools: string[] = [];\n\n for (const obj of this.selectMCPToolOwners(manifest)) {\n tools.push(...this.getSimpleMCPToolNames(obj));\n }\n\n return tools.join('\\n');\n }\n\n /**\n * Choose exactly one canonical MCP owner per `collection`.\n *\n * MCP tool names are keyed on `collection`, but the framework's normal shape\n * puts a model class and its `FooCollection` access class in the manifest\n * under the SAME collection. Emitting both produces duplicate tool names with\n * differing create/update schemas, and an MCP client that indexes tools by\n * name then resolves an arbitrary one (#2631 review).\n *\n * Owners are ranked, in order:\n *\n * 1. The model class beats the collection-access class. `create`/`update`\n * input schemas derive from `obj.fields`, and the row shape lives on the\n * model, not on the access class.\n * 2. The shallowest class in the collection's own inheritance tree wins. An\n * STI family shares one `collection`, and the base defines the shared row\n * contract; a leaf subclass would narrow the emitted schema to one variant\n * of a table the tool addresses as a whole.\n * 3. Remaining ties break lexically on the qualified name, so the emitted\n * surface is deterministic across generation passes.\n */\n private selectMCPToolOwners(\n manifest: SmartObjectManifest,\n ): SmartObjectDefinition[] {\n const candidatesByCollection = new Map<string, SmartObjectDefinition[]>();\n\n for (const obj of Object.values(manifest.objects)) {\n if (obj.decoratorConfig.mcp === false) continue;\n const bucket = candidatesByCollection.get(obj.collection);\n if (bucket) bucket.push(obj);\n else candidatesByCollection.set(obj.collection, [obj]);\n }\n\n return [...candidatesByCollection.entries()]\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n .map(([, candidates]) => {\n const depths = this.inheritanceDepthsWithin(candidates);\n let owner = candidates[0];\n for (const candidate of candidates.slice(1)) {\n if (this.preferMCPToolOwner(candidate, owner, depths)) {\n owner = candidate;\n }\n }\n return owner;\n });\n }\n\n /** Stable identity for an MCP owner candidate. */\n private mcpOwnerKey(obj: SmartObjectDefinition): string {\n return obj.qualifiedName || obj.className;\n }\n\n /**\n * Depth of each candidate inside the candidate set's OWN inheritance tree,\n * keyed by {@link mcpOwnerKey}. A candidate with no candidate ancestor is a\n * root at depth 0. Ancestors outside the set (framework bases, classes in\n * other collections) do not add depth: only the shared-collection family\n * decides which member is canonical.\n *\n * Parents resolve on `extendsQualified` first. Two packages may legally\n * contribute same-simple-name classes to one collection, so a simple-name\n * match is used only when it is unambiguous within the candidate set —\n * otherwise the walk stops rather than linking unrelated classes.\n */\n private inheritanceDepthsWithin(\n candidates: SmartObjectDefinition[],\n ): Map<string, number> {\n const byQualified = new Map<string, SmartObjectDefinition>();\n const bySimpleName = new Map<string, SmartObjectDefinition | null>();\n for (const candidate of candidates) {\n byQualified.set(this.mcpOwnerKey(candidate), candidate);\n const simple = this.simpleClassName(candidate.className);\n // `null` marks an ambiguous simple name; never resolve through it.\n bySimpleName.set(simple, bySimpleName.has(simple) ? null : candidate);\n }\n\n const resolveParent = (\n obj: SmartObjectDefinition,\n ): SmartObjectDefinition | undefined => {\n if (obj.extendsQualified) return byQualified.get(obj.extendsQualified);\n if (!obj.extends) return undefined;\n return bySimpleName.get(this.simpleClassName(obj.extends)) ?? undefined;\n };\n\n const depths = new Map<string, number>();\n for (const candidate of candidates) {\n const key = this.mcpOwnerKey(candidate);\n let depth = 0;\n let current: SmartObjectDefinition | undefined = candidate;\n const visited = new Set<string>([key]);\n while (current) {\n const parent: SmartObjectDefinition | undefined =\n resolveParent(current);\n if (!parent) break;\n const parentKey = this.mcpOwnerKey(parent);\n // Circular or self-referential extends: stop rather than loop.\n if (visited.has(parentKey)) break;\n visited.add(parentKey);\n depth += 1;\n current = parent;\n }\n depths.set(key, depth);\n }\n return depths;\n }\n\n /** True when `candidate` is the better canonical MCP owner than `current`. */\n private preferMCPToolOwner(\n candidate: SmartObjectDefinition,\n current: SmartObjectDefinition,\n depths: Map<string, number>,\n ): boolean {\n const candidateIsCollection = this.isCollectionAccessClass(candidate);\n const currentIsCollection = this.isCollectionAccessClass(current);\n if (candidateIsCollection !== currentIsCollection) {\n return !candidateIsCollection;\n }\n\n const candidateKey = this.mcpOwnerKey(candidate);\n const currentKey = this.mcpOwnerKey(current);\n\n const candidateDepth = depths.get(candidateKey) ?? 0;\n const currentDepth = depths.get(currentKey) ?? 0;\n if (candidateDepth !== currentDepth) {\n return candidateDepth < currentDepth;\n }\n\n return candidateKey < currentKey;\n }\n\n /**\n * Collection-access class detection, matching the convention already used by\n * `generateRestRoutes` (direct base / generic type argument) plus the\n * `FooCollection` naming fallback this generator uses elsewhere, so a deeper\n * subclass that carries no type argument of its own is still recognised.\n */\n private isCollectionAccessClass(obj: SmartObjectDefinition): boolean {\n return (\n obj.extends === 'SmrtCollection' ||\n !!obj.extendsTypeArg ||\n obj.className.endsWith('Collection')\n );\n }\n\n /**\n * Generate MCP tool JSON definitions\n */\n generateMCPToolsCode(manifest: SmartObjectManifest): string {\n const tools: string[] = [];\n\n for (const obj of this.selectMCPToolOwners(manifest)) {\n const code = this.generateMCPTool(obj);\n // An object whose every operation is excluded contributes nothing;\n // pushing '' would emit a hole in the array literal (#2631).\n if (code) tools.push(code);\n }\n\n return tools.length > 0 ? `[\\n${tools.join(',\\n')}\\n]` : '[]';\n }\n\n /**\n * Get simple MCP tool names for an object\n */\n private getSimpleMCPToolNames(obj: SmartObjectDefinition): string[] {\n const { collection } = obj;\n const config = obj.decoratorConfig.mcp;\n const exclude = (typeof config === 'object' && config?.exclude) || [];\n const include =\n (typeof config === 'object' && config?.include) || undefined;\n\n const tools: string[] = [];\n\n const shouldInclude = (op: string) => {\n if (include && !include.includes(op)) return false;\n if (exclude.includes(op)) return false;\n return true;\n };\n\n if (shouldInclude('list')) {\n tools.push(`list_${collection}`);\n }\n if (shouldInclude('get')) {\n tools.push(`get_${collection}`);\n }\n if (shouldInclude('create')) {\n tools.push(`create_${collection}`);\n }\n if (shouldInclude('update')) {\n tools.push(`update_${collection}`);\n }\n if (shouldInclude('delete')) {\n tools.push(`delete_${collection}`);\n }\n\n return tools;\n }\n\n /**\n * Generate a single MCP tool\n */\n private generateMCPTool(obj: SmartObjectDefinition): string {\n const { collection } = obj;\n const config = obj.decoratorConfig.mcp;\n const exclude = (typeof config === 'object' && config?.exclude) || [];\n const include =\n (typeof config === 'object' && config?.include) || undefined;\n\n const tools: string[] = [];\n\n const shouldInclude = (op: string) => {\n if (include && !include.includes(op)) return false;\n if (exclude.includes(op)) return false;\n return true;\n };\n\n if (shouldInclude('list')) {\n tools.push(` {\n name: \"list_${collection}\",\n description: \"List ${collection}\",\n inputSchema: {\n type: \"object\",\n properties: {\n limit: { type: \"number\" },\n offset: { type: \"number\" },\n where: { type: \"object\" }\n }\n }\n }`);\n }\n\n if (shouldInclude('get')) {\n tools.push(` {\n name: \"get_${collection}\",\n description: \"Get a ${collection} entry by ID\",\n inputSchema: {\n type: \"object\",\n properties: {\n id: { type: \"string\", description: \"The ${collection} entry ID\" }\n },\n required: [\"id\"]\n }\n }`);\n }\n\n const schemaProperties = JSON.stringify(\n this.generateSchemaProperties(obj.fields),\n null,\n 6,\n );\n\n if (shouldInclude('create')) {\n const requiredFields = Object.entries(obj.fields)\n .filter(([_, field]) => field.required)\n .map(([fieldName]) => fieldName);\n\n tools.push(` {\n name: \"create_${collection}\",\n description: \"Create a new ${collection} entry\",\n inputSchema: {\n type: \"object\",\n properties: ${schemaProperties},\n required: ${JSON.stringify(requiredFields)}\n }\n }`);\n }\n\n if (shouldInclude('update')) {\n tools.push(` {\n name: \"update_${collection}\",\n description: \"Update an existing ${collection} entry\",\n inputSchema: {\n type: \"object\",\n properties: {\n id: { type: \"string\", description: \"The ${collection} entry ID\" },\n data: {\n type: \"object\",\n description: \"Fields to update on the ${collection} entry\",\n properties: ${schemaProperties}\n }\n },\n required: [\"id\", \"data\"]\n }\n }`);\n }\n\n if (shouldInclude('delete')) {\n tools.push(` {\n name: \"delete_${collection}\",\n description: \"Delete a ${collection} entry by ID\",\n inputSchema: {\n type: \"object\",\n properties: {\n id: { type: \"string\", description: \"The ${collection} entry ID\" }\n },\n required: [\"id\"]\n }\n }`);\n }\n\n return tools.join(',\\n');\n }\n\n /**\n * Generate JSON schema properties for fields\n */\n private generateSchemaProperties(\n fields: Record<string, FieldDefinition>,\n ): Record<string, JsonSchemaProperty> {\n const properties: Record<string, JsonSchemaProperty> = {};\n\n for (const [name, field] of Object.entries(fields)) {\n properties[name] = {\n type: this.mapFieldTypeToJSON(field.type),\n description: field.description || `The ${name} field`,\n };\n\n if (field.min !== undefined) properties[name].minimum = field.min;\n if (field.max !== undefined) properties[name].maximum = field.max;\n if (field.minLength !== undefined)\n properties[name].minLength = field.minLength;\n if (field.maxLength !== undefined)\n properties[name].maxLength = field.maxLength;\n if (\n field.enum &&\n field.enum.length > 0 &&\n (field.type === 'text' ||\n field.type === 'integer' ||\n field.type === 'decimal')\n ) {\n properties[name].enum = [...field.enum];\n }\n }\n\n return properties;\n }\n\n /**\n * Map field types to JSON Schema types\n */\n private mapFieldTypeToJSON(fieldType: string): string {\n switch (fieldType) {\n case 'text':\n return 'string';\n case 'decimal':\n return 'number';\n case 'integer':\n return 'integer';\n case 'boolean':\n return 'boolean';\n case 'datetime':\n return 'string';\n case 'json':\n return 'object';\n case 'foreignKey':\n return 'string';\n case 'crossPackageRef':\n return 'string';\n default:\n return 'string';\n }\n }\n\n /**\n * Generate agent manifests for Agent subclasses (fifth pass).\n *\n * For any SmartObjectDefinition with `agent` in its decoratorConfig,\n * auto-generates:\n * - Permissions from uiSlots (manage:*) and CLI/MCP methods (execute:*)\n * - Features from uiSlots and exposed methods\n * - Menu items from uiSlots\n * - Component declarations from package.json exports\n *\n * @param manifest - The manifest to process in-place\n * @param packageName - Package name for component export paths\n * @param packageJson - Full package.json for component discovery\n */\n generateAgentManifests(\n manifest: SmartObjectManifest,\n packageName?: string,\n packageJson?: PackageJsonLike,\n ): void {\n for (const obj of Object.values(manifest.objects)) {\n if (!obj.decoratorConfig.agent) continue;\n\n const agentConfig = obj.decoratorConfig.agent;\n const slug = obj.className.toLowerCase();\n // staticProperties is an untyped AST capture; assert the shape the\n // scanner records for `static uiSlots` on Agent subclasses.\n const uiSlots: Record<string, AgentUISlotManifest> =\n (obj.staticProperties?.uiSlots as\n | Record<string, AgentUISlotManifest>\n | undefined) ?? {};\n\n // Derive permissions\n const permissions: AgentPermission[] = [];\n\n // From uiSlots: manage:<slotId>\n for (const [slotId, slot] of Object.entries(uiSlots)) {\n permissions.push({\n id: `manage:${slotId}`,\n label: `Manage ${(slot as AgentUISlotManifest).label || slotId}`,\n category: 'slot',\n defaultGranted: true,\n });\n }\n\n // From CLI/MCP methods: execute:<methodName>\n const exposedMethods = this.getExposedMethods(obj);\n for (const methodName of exposedMethods) {\n permissions.push({\n id: `execute:${methodName}`,\n label: `Execute ${methodName}`,\n category: 'method',\n defaultGranted: true,\n });\n }\n\n // Derive features\n const features: AgentFeature[] = [];\n\n for (const [slotId, slot] of Object.entries(uiSlots)) {\n const typedSlot = slot as AgentUISlotManifest;\n features.push({\n id: slotId,\n label: typedSlot.label || slotId,\n description: typedSlot.description,\n type: 'slot',\n });\n }\n\n for (const methodName of exposedMethods) {\n features.push({\n id: methodName,\n label: methodName,\n type: 'method',\n });\n }\n\n // Derive menu items from uiSlots (sorted by order)\n const menuItems: AgentMenuItem[] = Object.entries(uiSlots)\n .map(([slotId, slot]) => {\n const typedSlot = slot as AgentUISlotManifest;\n return {\n id: slotId,\n label: typedSlot.label || slotId,\n icon: typedSlot.icon,\n order: typedSlot.order ?? 999,\n path: `/agents/${slug}/${slotId}`,\n requiredPermission: `manage:${slotId}`,\n };\n })\n .sort((a, b) => a.order - b.order);\n\n // Derive component declarations from package.json exports\n const components: AgentComponentDeclaration[] = [];\n if (packageName && packageJson?.exports) {\n for (const [exportKey, exportValue] of Object.entries(\n packageJson.exports,\n )) {\n // Match patterns like './admin', './town', etc.\n if (exportKey === '.' || exportKey === './manifest') continue;\n\n // Check if this export has a svelte condition (component export)\n const hasSvelteCondition = this.hasSvelteExport(exportValue);\n if (hasSvelteCondition) {\n const type = exportKey.replace('./', '');\n components.push({\n exportPath: `${packageName}/${type}`,\n type,\n });\n }\n }\n }\n\n // Capture adminRoutes from static property (same pattern as uiSlots)\n const adminRoutes: AgentAdminRouteManifest[] =\n (obj.staticProperties?.adminRoutes as\n | AgentAdminRouteManifest[]\n | undefined) ?? [];\n\n // Capture createEntries (agent-contributed create options)\n const createEntries: AgentCreateEntryManifest[] =\n (obj.staticProperties?.createEntries as\n | AgentCreateEntryManifest[]\n | undefined) ?? [];\n\n // Capture signalSubscriptions from static property\n const signalSubscriptions: string[] =\n (obj.staticProperties?.signalSubscriptions as string[] | undefined) ??\n [];\n\n const agentManifest: AgentManifest = {\n name: obj.className,\n slug,\n icon: agentConfig.icon,\n tier: agentConfig.tier || 'free',\n description: agentConfig.description,\n uiSlots,\n ...(adminRoutes.length > 0 ? { adminRoutes } : {}),\n ...(createEntries.length > 0 ? { createEntries } : {}),\n ...(signalSubscriptions.length > 0 ? { signalSubscriptions } : {}),\n permissions,\n features,\n menuItems,\n components,\n };\n\n obj.agent = agentManifest;\n\n logger.debug(\n `[manifest-generator] Generated agent manifest for ${obj.className}: ` +\n `${permissions.length} permissions, ${features.length} features, ` +\n `${menuItems.length} menu items, ${components.length} components`,\n );\n }\n }\n\n /**\n * Get deduplicated list of method names exposed via CLI and MCP config\n */\n private getExposedMethods(obj: SmartObjectDefinition): string[] {\n const methods = new Set<string>();\n\n const cliConfig = obj.decoratorConfig.cli;\n if (cliConfig && typeof cliConfig === 'object' && cliConfig.include) {\n for (const m of cliConfig.include) {\n methods.add(m);\n }\n }\n\n const mcpConfig = obj.decoratorConfig.mcp;\n if (mcpConfig && typeof mcpConfig === 'object' && mcpConfig.include) {\n for (const m of mcpConfig.include) {\n methods.add(m);\n }\n }\n\n return Array.from(methods);\n }\n\n /**\n * Check if an export value has a svelte condition (indicating a component export)\n */\n private hasSvelteExport(exportValue: unknown): boolean {\n if (!exportValue || typeof exportValue !== 'object') return false;\n\n // Check for { svelte: ... } condition\n if ('svelte' in exportValue) return true;\n\n // Check nested conditions like { import: { svelte: ... } }\n for (const val of Object.values(exportValue)) {\n if (val && typeof val === 'object' && 'svelte' in (val as object)) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Save manifest to file\n */\n saveManifest(manifest: SmartObjectManifest, filePath: string): void {\n const fs = require('node:fs');\n fs.writeFileSync(filePath, JSON.stringify(manifest, null, 2));\n }\n\n /**\n * Load manifest from file\n */\n loadManifest(filePath: string): SmartObjectManifest {\n const fs = require('node:fs');\n const content = fs.readFileSync(filePath, 'utf-8');\n return JSON.parse(content);\n }\n}\n\n/**\n * Convenience function to generate manifest\n *\n * @param scanResults - Array of scan results containing object definitions\n * @param options - Optional configuration (passed to ManifestGenerator.generateManifest)\n */\nexport function generateManifest(\n scanResults: ScanResult[],\n options?: {\n packageName?: string;\n packageVersion?: string;\n packageJson?: PackageJsonLike;\n smrtDependencies?: string[];\n includeVisibility?: SmrtVisibility[];\n },\n): SmartObjectManifest {\n const generator = new ManifestGenerator();\n return generator.generateManifest(scanResults, options);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"manifest-generator.js","names":[],"sources":["../../src/scanner/manifest-generator.ts"],"sourcesContent":["/**\n * Manifest generator for creating service manifests from AST scan results\n */\n\nimport { createHash } from 'node:crypto';\nimport { createRequire } from 'node:module';\nimport { createLogger } from '@happyvertical/logger';\nimport { ConfigurationError } from '../errors.js';\nimport {\n createManifestClassNamePredicate,\n resolveApiMethodExposure,\n resolveCustomActionMetadata,\n resolveEffectiveActionMetadata,\n} from '../generators/custom-action.js';\nimport {\n loadExternalManifestSync,\n lookupInManifest,\n} from '../manifest/manifest-loader.js';\nimport { findField, type HelpModel, validateHelp } from '../recipe-help.js';\nimport {\n findCollectionWriteEscalations,\n formatCollectionWriteEscalations,\n inheritCollectionExposure,\n} from '../registry/collection-exposure.js';\nimport { isSmrtCollectionExtendsName } from '../registry/collection-resolution.js';\nimport { VERBOSE_ENABLED } from '../registry/shared-state.js';\nimport {\n findStaleWidenings,\n findSubclassExposureEscalations,\n formatSubclassExposureEscalations,\n inheritSubclassExposure,\n} from '../registry/subclass-exposure.js';\nimport type { SmartObjectConfig } from '../registry/types.js';\nimport {\n defaultConflictColumns,\n resolveOwnershipTenantColumn,\n resolveTenantColumn,\n} from '../schema/conflict-target.js';\nimport type { DatabaseEngine } from '../schema/ddl/types.js';\nimport {\n resolveForeignKeyDeleteAction,\n resolveForeignKeyUpdateAction,\n} from '../schema/foreign-key-policy.js';\nimport { SchemaGenerator } from '../schema/generator.js';\nimport type {\n ColumnDefinition,\n SchemaDefinition,\n SQLDataType,\n} from '../schema/types.js';\nimport { generateToolManifest } from '../tools/tool-generator.js';\nimport {\n displayLabelFieldProblem,\n FIELD_UI_FORMAT_TYPES,\n FIELD_UI_FORMATS,\n FIELD_UI_WIDGET_TYPES,\n FIELD_UI_WIDGETS,\n isFieldUIFormat,\n isFieldUIWidget,\n isRelationshipRole,\n RELATIONSHIP_ROLES,\n resolveDisplayLabelField,\n} from '../ui-metadata.js';\nimport { classnameToTablename, toSnakeCase } from '../utils/naming.js';\nimport {\n assertScopedPackageName,\n createQualifiedName,\n isQualifiedName,\n isQualifiedNameAliasFormat,\n parseQualifiedName,\n readPreviousQualifiedNames,\n} from '../utils/qualified-names.js';\nimport { applyRecipeDemo } from './recipe-demo-pass.js';\nimport { isTestFile } from './test-file-patterns.js';\nimport type {\n AgentAdminRouteManifest,\n AgentComponentDeclaration,\n AgentCreateEntryManifest,\n AgentFeature,\n AgentManifest,\n AgentMenuItem,\n AgentPermission,\n AgentUISlotManifest,\n FieldDefinition,\n ManifestColumnDefinition,\n ManifestSchema,\n MethodDefinition,\n ScanResult,\n SmartObjectDefinition,\n SmartObjectManifest,\n SmrtVisibility,\n ValidationRule,\n} from './types.js';\nimport { MANIFEST_TIMESTAMP } from './types.js';\n\n/** Package.json shape consumed for import-path and component discovery. */\ninterface PackageJsonLike {\n name?: string;\n main?: string;\n exports?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\n/**\n * Object form of the `@smrt({ tenantScoped })` config. Mirrors the object\n * branch of `SmartObjectConfig['tenantScoped']`; all keys optional because\n * the boolean shorthand normalizes to `{}`.\n */\ninterface TenantScopedOptions {\n mode?: 'required' | 'optional';\n field?: string;\n autoFilter?: boolean;\n autoPopulate?: boolean;\n allowSuperAdminBypass?: boolean;\n}\n\n/** JSON Schema property entry emitted for a field in generated MCP tools. */\ninterface JsonSchemaProperty {\n type: string;\n description: string;\n minimum?: number;\n maximum?: number;\n minLength?: number;\n maxLength?: number;\n enum?: Array<string | number>;\n}\n\ntype SchemaGeneratorLike = {\n generateSQL: (schema: SchemaDefinition, engine?: DatabaseEngine) => string;\n};\n\n// Create require function for synchronous module loading in ESM context\nconst require = createRequire(import.meta.url);\n\n// Build-time schema/manifest-generation diagnostics route through the shared\n// logger (S14 / dim-9, #1579) instead of unconditional stdout writes. Level\n// follows the repo-wide SMRT_VERBOSE/DEBUG convention (#2896) so per-class\n// detail is opt-in rather than always-on info.\nconst logger = createLogger({ level: VERBOSE_ENABLED ? 'debug' : 'info' });\n\n/**\n * Fields every `SmrtObject` carries that are not manifest fields (#3590): a\n * recipe option may still refine them.\n */\nconst UNIVERSAL_OBJECT_FIELDS = [\n 'id',\n 'slug',\n 'context',\n 'created_at',\n 'updated_at',\n];\n\n/**\n * Framework abstract base classes whose declared fields must be merged\n * into every subclass's `fields` map.\n *\n * These classes live in SMRT framework packages, have no `@smrt()`\n * decorator, no table of their own, and contribute structural fields\n * (e.g. `SmrtHierarchical.parentId`) that subclasses query against —\n * without merging, downstream WHERE-clause validation rejects queries on\n * those columns.\n *\n * SmrtObject / SmrtClass / SmrtCollection are intentionally NOT in this\n * set even though they live in core. SmrtObject's universal columns\n * (`id`, `slug`, `context`, `created_at`, `updated_at`) are added by a\n * separate universal-baseline mechanism in `fieldsFromClass`, and merging\n * them here would double-write with subtly different `_meta` payloads\n * and regress existing field expectations.\n *\n * Keep in sync with `FRAMEWORK_BASE_CLASSES` in\n * `packages/scanner/src/inheritance-resolver.ts` — note that set is\n * broader: it controls scanner-level chain termination and stub\n * resolution, while this one only controls field merging.\n */\nconst FRAMEWORK_ABSTRACT_BASE_NAMES = new Set([\n 'SmrtJunction',\n 'SmrtJunctionBase',\n 'SmrtHierarchical',\n 'SmrtPolymorphicAssociation',\n 'SmrtReport',\n 'SmrtReportCollection',\n]);\n\n/**\n * Framework base classes to exclude from the ancestor **method** merge\n * below (#2624). Unlike fields, methods are never columns, so they never\n * needed the STI-vs-CTI field-merge rule above — they inherited it only by\n * sharing the same loop.\n *\n * Deliberately NARROWER than `FRAMEWORK_ABSTRACT_BASE_NAMES`: only the\n * three universal object/collection primitives (`SmrtObject`, `SmrtClass`,\n * `SmrtCollection`) are internal-only. These are the same three the\n * runtime resolver's `getAllMethods()`\n * (`packages/core/src/registry/inheritance-resolver.ts`) explicitly skips\n * by name, and the same three the field-merge doc comment above excludes\n * from `FRAMEWORK_ABSTRACT_BASE_NAMES` for the identical reason: their\n * surface (`save`, `destroy`, `toJSON`, `withTransaction`, ...) is generic\n * object-lifecycle plumbing, never a subclass-specific action.\n *\n * `FRAMEWORK_ABSTRACT_BASE_NAMES` (`SmrtJunction`, `SmrtHierarchical`,\n * `SmrtPolymorphicAssociation`, `SmrtReport`, `SmrtReportCollection`) is\n * intentionally NOT folded in here, unlike an earlier version of this fix.\n * Those classes are mixin-style bases whose declared methods ARE the\n * subclass's real, intended public API — the same way `SmrtHierarchical.\n * parentId` is a real, intended field, which is exactly why\n * `FRAMEWORK_ABSTRACT_BASE_NAMES` fields already merge into every subclass\n * regardless of STI/CTI (see above). Directly confirmed for two of the\n * five: `SmrtJunction.attach`/`detach`/`byLeft`/`byRight`/`setLinks`\n * (`packages/core/src/junction.ts`) — a `packages/template-sveltekit/\n * __tests__/runtimeProfileParity.test.ts` snapshot broke when an earlier\n * revision of this fix folded all 8 `FRAMEWORK_BASE_CLASSES` in here,\n * which is how this got caught — and `SmrtHierarchical.getParent`/\n * `getChildren`/`getAncestors`/`getDescendants`/`getHierarchy`/`moveTo`\n * (`packages/core/src/hierarchical.ts`). `SmrtPolymorphicAssociation`\n * follows the identical pattern by inspection but has no dedicated\n * regression test yet. `SmrtReport`/`SmrtReportCollection` are the\n * least-audited of the five: `SmrtReportCollection` overrides `list`/`get`\n * (`packages/reports/src/report.ts`), which are also the universal CRUD\n * operation names — a downstream `class X extends SmrtReportCollection`\n * with default (non-strict) MCP config would have seen a generated\n * custom-action tool collide with the standard `list`/`get` tool name.\n * #2646 closed that separately and independently of this exclusion set: the\n * MCP generator now refuses to expose a CRUD-named method as a custom action,\n * matching case-folded because its tool ids are lowercased whole. Each emitter\n * reserves on its own terms, and not all of them read the shared\n * `CRUD_OPERATIONS` list yet — see its docblock in\n * `generators/custom-action.ts` for the per-emitter rules. Keep in sync with the field-merge set's own doc comment; this one\n * governs method merging only.\n */\nconst FRAMEWORK_METHOD_BASE_NAMES = new Set([\n 'SmrtObject',\n 'SmrtClass',\n 'SmrtCollection',\n]);\n\n/**\n * Deterministic string comparator (#2749). Manifest object iteration order\n * follows scan/discovery order, which is not stable across runs, so any\n * emitted artifact keyed off `Object.entries(manifest.objects)` needs a\n * stable sort before emission.\n */\nfunction compareText(left: string, right: string): number {\n if (left < right) return -1;\n if (left > right) return 1;\n return 0;\n}\n\n/**\n * True when a package.json `exports` condition resolves to a non-JS asset\n * (e.g. the `./manifest`/`./manifest.json` convention pointing at\n * `dist/manifest.json`), so subpath matching (smrt#2845's\n * `matchExportsSubpath`) never attributes a scanned object to it — no\n * `@smrt()` class's source file can be loaded from a JSON target.\n */\nfunction targetsJsonAsset(condition: unknown): boolean {\n if (typeof condition === 'string') return condition.endsWith('.json');\n if (condition && typeof condition === 'object') {\n const record = condition as Record<string, unknown>;\n const target = record.import ?? record.default ?? record.require;\n return typeof target === 'string' && target.endsWith('.json');\n }\n return false;\n}\n\n/**\n * Infer visibility from file path and explicit config\n *\n * Priority:\n * 1. Explicit visibility in decorator config\n * 2. Auto-detect test files → 'test'\n * 3. Default to 'public'\n */\nfunction inferVisibility(\n filePath: string,\n explicitVisibility?: SmrtVisibility,\n): SmrtVisibility {\n if (explicitVisibility) return explicitVisibility;\n if (isTestFile(filePath)) return 'test';\n return 'public';\n}\n\nexport class ManifestGenerator {\n /**\n * Generate manifest from scan results\n *\n * @param scanResults - Array of scan results containing object definitions\n * @param options - Optional configuration\n * @param options.packageName - Package name to inject into manifest and object definitions\n * @param options.packageVersion - Package version\n * @param options.packageJson - Full package.json object for determining import paths\n * @param options.smrtDependencies - List of SMRT package dependencies to include in manifest\n * @param options.includeVisibility - Array of visibility levels to include (default: all)\n * - For published packages: ['public']\n * - For development: ['public', 'internal', 'test'] or omit for all\n */\n generateManifest(\n scanResults: ScanResult[],\n options?: {\n packageName?: string;\n packageVersion?: string;\n packageJson?: PackageJsonLike;\n smrtDependencies?: string[];\n includeVisibility?: SmrtVisibility[];\n },\n ): SmartObjectManifest {\n const manifest: SmartObjectManifest = {\n version: '1.0.0',\n timestamp: MANIFEST_TIMESTAMP,\n objects: {},\n };\n\n if (scanResults.some((result) => result.objects.length > 0)) {\n assertScopedPackageName(options?.packageName);\n }\n\n // Set package metadata at manifest level if provided\n if (options?.packageName) {\n manifest.packageName = options.packageName;\n }\n if (options?.packageVersion) {\n manifest.packageVersion = options.packageVersion;\n }\n // Set smrtDependencies BEFORE mergeInheritedFields() so external packages can be loaded\n if (options?.smrtDependencies) {\n manifest.smrtDependencies = options.smrtDependencies;\n }\n\n for (const result of scanResults) {\n for (const objectDef of result.objects) {\n // Set package metadata on object definition if provided\n if (options?.packageName) {\n objectDef.packageName = options.packageName;\n }\n if (options?.packageVersion) {\n objectDef.packageVersion = options.packageVersion;\n }\n\n // Generate qualified name (required for manifest keying)\n // Must have packageName to generate qualified name\n if (objectDef.packageName) {\n objectDef.qualifiedName = createQualifiedName(\n objectDef.packageName,\n objectDef.className,\n );\n }\n\n // Infer visibility from file path and decorator config\n objectDef.visibility = inferVisibility(\n objectDef.filePath,\n objectDef.decoratorConfig?.visibility as SmrtVisibility | undefined,\n );\n\n // Filter by visibility if specified\n // Skip objects that don't match the requested visibility levels\n if (\n options?.includeVisibility &&\n options.includeVisibility.length > 0 &&\n !options.includeVisibility.includes(objectDef.visibility)\n ) {\n // Skip this object - visibility not in allowed list\n continue;\n }\n\n // Determine import path from package.json exports\n if (options?.packageName && options?.packageJson) {\n objectDef.importPath = this.determineImportPath(\n options.packageJson,\n objectDef.filePath,\n );\n }\n\n // Set export names (defaults to className)\n objectDef.exportName = objectDef.exportName || objectDef.className;\n objectDef.collectionExportName =\n objectDef.collectionExportName || `${objectDef.className}Collection`;\n\n // Generate AI tools from methods if AI config exists\n if (objectDef.decoratorConfig.ai) {\n const methods = Object.values(objectDef.methods);\n const tools = generateToolManifest(\n methods,\n objectDef.decoratorConfig.ai,\n );\n\n // Store tools in object definition\n if (tools.length > 0) {\n objectDef.tools = tools;\n }\n }\n\n // Determine manifest key: use qualified name if available, fall back to lowercase name\n // During transition, some objects may not have qualified names\n const manifestKey = objectDef.qualifiedName || objectDef.name;\n\n // Check for collisions using the manifest key\n if (manifest.objects[manifestKey]) {\n const existing = manifest.objects[manifestKey];\n throw new Error(\n `Class name collision detected: '${objectDef.className}' (${manifestKey}) is defined in multiple files:\\n` +\n ` 1. ${existing.filePath}\\n` +\n ` 2. ${objectDef.filePath}\\n\\n` +\n `Class names must be unique within a package. Use different class names or separate packages.`,\n );\n }\n\n manifest.objects[manifestKey] = objectDef;\n }\n }\n\n this.applyGenerationPasses(manifest, {\n packageName: options?.packageName,\n packageJson: options?.packageJson,\n });\n\n return manifest;\n }\n\n /**\n * Run every manifest generation pass, in order, on a manifest whose\n * `objects` have been collected. This is THE pass sequence: the OXC vite\n * plugin (`vite-plugin/index.ts`) and `ManifestBuilder.buildManifest()`\n * call it too, so the three producers cannot drift — before #2360\n * `ManifestBuilder` skipped the report passes and its manifests carried\n * `(slug, context)` conflict indexes for `@report` classes while the\n * runtime upserted on the report's group columns.\n *\n * @param manifest - manifest with `objects` populated (and\n * `smrtDependencies` set, so external STI bases resolve)\n * @param options - package metadata for the agent-manifest pass\n */\n applyGenerationPasses(\n manifest: SmartObjectManifest,\n options?: { packageName?: string; packageJson?: PackageJsonLike },\n ): void {\n // An unscoped package name would yield `pkg:Class` keys the registry\n // rejects at startup (#3408); fail here with an actionable message. An app\n // that declares no classes generates no qualified names and still builds.\n if (Object.keys(manifest.objects).length > 0) {\n assertScopedPackageName(options?.packageName);\n }\n\n // Capture authored API exposure before making the abstract class itself\n // read-only so hosted concrete descendants can inherit the authored part.\n for (const objectDef of Object.values(manifest.objects)) {\n if (objectDef.decoratorConfig?.abstract !== true) continue;\n if (!Object.hasOwn(objectDef, 'abstractDeclaredApi')) {\n objectDef.abstractDeclaredApi = objectDef.decoratorConfig.api ?? null;\n }\n }\n\n // Deprecated qualified-name aliases (#3338) fail closed at build time, the\n // same as the registry refuses them at runtime.\n this.assertQualifiedNameAliases(manifest);\n\n // Keep only import-derived parent qualifications the parent's package\n // confirms (#4145), before any pass walks `extendsQualified`.\n this.verifyImportedParents(manifest);\n\n // Report cache rows are safe to scope by tenant even when a report is\n // global: optional mode keeps tenant-less rows readable outside a tenant\n // context and gives tenant-scoped reports the tenant_id column their raw\n // aggregate refresh path must write.\n this.normalizeReportTenantScope(manifest);\n\n // Second pass: materialize implicit tenant fields before inheritance and schema generation.\n this.injectTenantScopedFields(manifest);\n\n // Report models default to a read-only surface. Apply that before\n // inheritance, so a report model's collection inherits it and the\n // collection-exposure guard sees it.\n this.applyReportSurfaceDefaults(manifest);\n\n // Third pass: Merge inherited fields for STI classes\n // This ensures STI subclasses have all parent fields inline in the manifest\n this.mergeInheritedFields(manifest);\n\n // A model subclass may narrow its parent's generated surface but not\n // widen it. Before the abstract pass below, which synthesizes write\n // exclusions on an abstract parent that its concrete subclasses exist to\n // lift.\n this.assertSubclassExposure(manifest);\n\n // All producers, including OXC, must suppress custom actions on abstract\n // resources and their collection classes. Do this after inheritance so\n // ancestor methods are covered and projections share the same exclusions.\n const objectsByName = new Map(\n Object.values(manifest.objects).map((objectDef) => [\n objectDef.className,\n objectDef,\n ]),\n );\n for (const objectDef of Object.values(manifest.objects)) {\n const config = objectDef.decoratorConfig;\n const isCollection =\n objectDef.extends === 'SmrtCollection' ||\n this.extendsCollection(objectDef, objectsByName, manifest);\n let collectionItem: SmartObjectDefinition | undefined;\n if (isCollection) {\n const seenParents = new Set<string>();\n let candidate: SmartObjectDefinition | undefined = objectDef;\n while (candidate) {\n if (candidate.extendsTypeArg || candidate.fields._itemClass) {\n collectionItem = this.findItemClass(\n candidate,\n manifest,\n objectsByName,\n );\n break;\n }\n const parentName = candidate.extendsQualified || candidate.extends;\n if (!parentName || seenParents.has(parentName)) break;\n seenParents.add(parentName);\n candidate = lookupInManifest(manifest, parentName) as\n | SmartObjectDefinition\n | undefined;\n }\n collectionItem ??= this.findItemClass(\n objectDef,\n manifest,\n objectsByName,\n );\n }\n const itemIsAbstract = collectionItem?.decoratorConfig?.abstract === true;\n if (config?.abstract !== true && !itemIsAbstract) continue;\n const methods = Object.entries(objectDef.methods || {})\n .filter(([, method]) => method.isPublic)\n .map(([name]) => name)\n .filter((name) => name !== 'list' && name !== 'get');\n for (const surface of ['api', 'mcp', 'cli'] as const) {\n if (config[surface] === false) continue;\n const current = config[surface];\n const excludes =\n current && typeof current === 'object' && current.exclude\n ? current.exclude\n : [];\n config[surface] = {\n ...(current && typeof current === 'object' ? current : {}),\n exclude: [\n ...new Set([...excludes, 'create', 'update', 'delete', ...methods]),\n ],\n };\n }\n }\n\n // A collection may not open a generated write its model closes. After\n // the abstract pass above, which closes writes over abstract models.\n this.assertCollectionExposure(manifest);\n\n // Recipe options may only name fields the merged model declares (#3590).\n this.assertRecipeOptions(manifest);\n this.assertRecipeHelp(manifest);\n // Browser capability of the package and the demo mode of its recipes (#3709).\n applyRecipeDemo(manifest, options?.packageName);\n\n // Presentation metadata (#3599): widget hints, display label, selector\n // bindings. After inheritance so a label may name an inherited STI column.\n this.applyUiMetadata(manifest);\n\n // Report models are read-only cache tables. Fill in the generated surface\n // and natural conflict key from report metadata before schema generation.\n this.normalizeReportObjects(manifest);\n\n // Tenant-scoped classes key on `[tenant column, ...natural key]` (#2360);\n // materialize that default so schema generation, the knowledge artifact\n // and the runtime read the same conflict target.\n this.normalizeConflictColumns(manifest);\n\n // Fourth pass: Generate validation rules for all objects\n // This pre-computes validation rules from field definitions, eliminating\n // the need to compile validator closures at runtime (Issue #782)\n this.generateValidationRules(manifest);\n\n // Fifth pass: Generate schemas for each object (build-time schema generation)\n // This pre-computes DDL, indexes, and columns for efficient external package consumption\n this.generateSchemas(manifest);\n this.assertTenantScopedSchemaContract(manifest);\n\n // Sixth pass: Generate agent manifests for Agent subclasses\n // Derives permissions, features, menuItems, and components from code\n this.generateAgentManifests(\n manifest,\n options?.packageName,\n options?.packageJson,\n );\n\n // Seventh pass: stamp the subpath consumers should import each object\n // from. `generateManifest()`'s own per-object loop already does this,\n // but the Vite plugin and `ManifestBuilder` (the other two manifest\n // producers this pass sequence exists to keep from drifting, #2360)\n // build their manifest via `ManifestAdapter.toManifest()` and call\n // `applyGenerationPasses()` directly — never through `generateManifest()`\n // — so their objects reached this pass with no `importPath` at all. That\n // is smrt#2845: `DataSurfaceActionIdempotencyState` in\n // `@happyvertical/smrt-agents` lives under `src/server/` (served only by\n // the `./server` export), but the published manifest carried no\n // `importPath`, so consumer registration\n // (`consumer-plugin/index.ts`'s own `determineImportPath`) fell back to\n // the bare package specifier the object was never exported from.\n this.resolveImportPaths(\n manifest,\n options?.packageName,\n options?.packageJson,\n );\n }\n\n /**\n * Drop an `extendsQualified` naming ANOTHER package unless that package's\n * manifest declares the class under exactly that qualified name (#4145).\n *\n * The scanner qualifies a parent from the import it is bound to, but a\n * module can re-export another package's class, and an alias-like specifier\n * (`@app/models`) can look like a package. Neither may become a parent the\n * registry cannot find, so an unconfirmed qualification falls back to the\n * simple `extends` and today's resolution. Same-package qualifications are\n * left alone: they name this manifest's own classes.\n */\n verifyImportedParents(manifest: SmartObjectManifest): void {\n for (const obj of Object.values(manifest.objects)) {\n const parent = obj.extendsQualified;\n if (!parent || !isQualifiedName(parent)) continue;\n const { packageName } = parseQualifiedName(parent);\n if (packageName === (obj.packageName ?? manifest.packageName)) continue;\n const parentManifest = loadExternalManifestSync(packageName, {\n warn: false,\n });\n if (parentManifest && lookupInManifest(parentManifest, parent)) continue;\n logger.debug(\n `[manifest-generator] ${obj.className}: ${packageName} does not declare ${parent}; keeping the unqualified parent \"${obj.extends}\"`,\n );\n delete obj.extendsQualified;\n }\n }\n\n /**\n * The name to resolve an object's parent by: the import-derived qualified\n * name when the scanner traced one (#4145), else the simple `extends`.\n */\n private parentRef(obj: SmartObjectDefinition): string | undefined {\n return obj.extendsQualified || obj.extends;\n }\n\n /**\n * Resolve a parent reference from {@link parentRef}. A qualified reference\n * matches only that package's class (this manifest's, else the dependency's\n * manifest), never a same-named class of another package; a simple one\n * keeps the established local-then-dependency lookup. `child` is skipped so\n * a local class named like its imported parent never resolves to itself.\n */\n private resolveParentDefinition(\n ref: string,\n child: SmartObjectDefinition | undefined,\n manifest: SmartObjectManifest,\n objectsByName: Map<string, SmartObjectDefinition>,\n ): SmartObjectDefinition | undefined {\n let parent: SmartObjectDefinition | undefined = isQualifiedName(ref)\n ? (manifest.objects[ref] as SmartObjectDefinition | undefined)\n : objectsByName.get(ref);\n if (parent === child) parent = undefined;\n if (!parent && manifest.smrtDependencies?.length) {\n parent = this.loadParentFromExternalPackage(\n ref,\n manifest.smrtDependencies,\n objectsByName,\n );\n }\n return parent === child ? undefined : parent;\n }\n\n /**\n * `obj`'s parent among `objectsByName` (keyed by class name), without\n * loading dependency manifests. An import-qualified parent only matches a\n * definition of that package, never a same-named class of another one\n * (#4176); a definition carrying no package identity still matches by name.\n * `manifest` is the one `objectsByName` was built from, where a qualified\n * parent that lost its class-name slot is still found.\n */\n private namedParent(\n obj: SmartObjectDefinition,\n objectsByName: Map<string, SmartObjectDefinition>,\n manifest?: SmartObjectManifest,\n ): SmartObjectDefinition | undefined {\n const qualified = obj.extendsQualified;\n if (!qualified) {\n return obj.extends ? objectsByName.get(obj.extends) : undefined;\n }\n const direct = objectsByName.get(qualified);\n if (direct) return direct;\n const identity = (candidate: SmartObjectDefinition) =>\n candidate.qualifiedName ??\n (candidate.packageName\n ? `${candidate.packageName}:${candidate.className}`\n : undefined);\n const candidate = objectsByName.get(this.simpleClassName(qualified));\n if (candidate && (identity(candidate) ?? qualified) === qualified) {\n return candidate;\n }\n // The class-name slot may hold another package's same-named class; the\n // imported one is then still in the manifest the map was built from.\n const keyed = manifest?.objects[qualified] as\n | SmartObjectDefinition\n | undefined;\n if (keyed) return keyed;\n for (const definition of [\n ...objectsByName.values(),\n ...Object.values(manifest?.objects ?? {}),\n ] as SmartObjectDefinition[]) {\n if (identity(definition) === qualified) return definition;\n }\n return undefined;\n }\n\n /**\n * Stamp `importPath` (via {@link determineImportPath}) on every object\n * that does not already have one. Safe to call unconditionally: objects\n * that went through `generateManifest()`'s own inline assignment already\n * carry an `importPath` and are left untouched.\n */\n resolveImportPaths(\n manifest: SmartObjectManifest,\n packageName?: string,\n packageJson?: PackageJsonLike,\n ): void {\n if (!packageName || !packageJson) return;\n\n for (const obj of Object.values(manifest.objects)) {\n if (obj.importPath) continue;\n obj.importPath = this.determineImportPath(packageJson, obj.filePath);\n }\n }\n\n /**\n * Materialize tenantScoped schema fields.\n *\n * Runtime registration already injects tenant fields for\n * `@smrt({ tenantScoped: true })`, but published manifests must contain the\n * same field before schema generation so migrations create `tenant_id`.\n */\n injectTenantScopedFields(manifest: SmartObjectManifest): void {\n for (const objectDef of Object.values(manifest.objects)) {\n this.injectTenantScopedField(objectDef);\n }\n }\n\n private injectTenantScopedField(objectDef: SmartObjectDefinition): void {\n const tenantScoped = objectDef.decoratorConfig?.tenantScoped;\n if (!tenantScoped) {\n return;\n }\n\n const { tenantConfig } = this.normalizeTenantScopedConfig(tenantScoped);\n const fieldName = tenantConfig.field;\n const existingField = objectDef.fields[fieldName];\n const tenancyMeta = {\n isTenantIdField: true,\n ...tenantConfig,\n };\n\n if (existingField) {\n const fieldTypeFailure = this.getTenantScopedFieldTypeFailure(\n objectDef,\n fieldName,\n );\n if (fieldTypeFailure) {\n throw new Error(\n `Tenant-scoped field configuration invalid: ${fieldTypeFailure}`,\n );\n }\n\n existingField._meta = {\n ...existingField._meta,\n sqlType: 'UUID',\n __tenancy: {\n ...existingField._meta?.__tenancy,\n ...tenancyMeta,\n },\n };\n return;\n }\n\n objectDef.fields[fieldName] = {\n type: 'text',\n // Use the normalized tenant mode so the boolean shorthand has the same\n // requiredness in manifests as it does during runtime registration.\n required: tenantConfig.mode === 'required',\n _meta: {\n generated: true,\n source: 'tenantScoped_decorator',\n sqlType: 'UUID',\n __tenancy: tenancyMeta,\n },\n };\n\n logger.debug(\n `[manifest-generator] Injected ${fieldName} field for ${objectDef.className} (tenantScoped: ${JSON.stringify(tenantConfig)})`,\n );\n }\n\n /**\n * Fail the build when a recipe's `options` name a field its model does not\n * declare (#3590). Runs after inherited fields merge, because only the merged\n * manifest knows STI-merged, injected tenant, and framework-base fields\n * (`SmrtHierarchical.parentId`); the scanner sees class bodies alone. The\n * universal `SmrtObject` fields exist on every object but are not manifest\n * fields, so they are accepted by name.\n */\n assertRecipeOptions(manifest: SmartObjectManifest): void {\n const problems: string[] = [];\n for (const recipe of manifest.recipes ?? []) {\n for (const entry of recipe.nav) {\n if (!entry.filter) continue;\n const object = Object.values(manifest.objects).find(\n (candidate) =>\n (candidate.qualifiedName ?? candidate.className) === entry.model,\n );\n if (\n object &&\n !Object.keys(object.fields).includes(entry.filter.field) &&\n !UNIVERSAL_OBJECT_FIELDS.includes(entry.filter.field as never)\n ) {\n problems.push(\n `recipe ${recipe.id}: nav \"${entry.label}\" filters on \"${entry.filter.field}\", which ${object.className} does not declare`,\n );\n }\n }\n for (const [model, options] of Object.entries(recipe.options ?? {})) {\n const object = Object.values(manifest.objects).find(\n (candidate) =>\n (candidate.qualifiedName ?? candidate.className) === model,\n );\n if (!object) {\n problems.push(\n `recipe ${recipe.id}: options name ${model}, which is not an object in this package`,\n );\n continue;\n }\n const declared = new Set([\n ...Object.keys(object.fields),\n ...UNIVERSAL_OBJECT_FIELDS,\n ]);\n for (const field of Object.keys(options.fields ?? {})) {\n if (!declared.has(field)) {\n problems.push(\n `recipe ${recipe.id}: options.${object.className}.fields.${field}: ${object.className} declares no field \"${field}\"; options only refine fields the model already declares`,\n );\n }\n }\n }\n }\n if (problems.length > 0) {\n throw new Error(\n `[manifest-generator] invalid recipe options:\\n ${problems.join('\\n ')}`,\n );\n }\n }\n\n /**\n * Fail the build when a recipe's help refers to a field its models do not\n * declare, or its `fieldRefs` disagree with the Markdown (#3591). Runs on the\n * merged manifest for the same reason as {@link assertRecipeOptions}. The\n * scanner derives `fieldRefs` with its own copy of the reference grammar\n * (it cannot import core); re-deriving here with the real parser means the\n * two can never silently diverge.\n */\n assertRecipeHelp(manifest: SmartObjectManifest): void {\n const problems: string[] = [];\n for (const recipe of manifest.recipes ?? []) {\n if (!recipe.help) continue;\n const models: HelpModel[] = [];\n const sensitiveByModel = new Map<string, Set<string>>();\n for (const model of recipe.models) {\n const object = Object.values(manifest.objects).find(\n (candidate) =>\n (candidate.qualifiedName ?? candidate.className) === model,\n );\n if (!object) continue;\n const sensitive = Object.entries(object.fields)\n .filter(\n ([, field]) =>\n field.sensitive === true || field._meta?.sensitive === true,\n )\n .map(([name]) => name);\n models.push({\n id: model,\n name: object.className,\n // Declared fields only: the universal ones (`slug`, `id`, ...) are not\n // manifest fields, so they never reach the knowledge artifact and a\n // host building its field list from it would drop the step.\n fields: Object.keys(object.fields).map((name) => ({\n name,\n label: name,\n visibility: 'basic',\n })),\n });\n sensitiveByModel.set(object.className, new Set(sensitive));\n }\n for (const problem of validateHelp(recipe.help, models)) {\n problems.push(`recipe ${recipe.id}: help: ${problem}`);\n }\n // Sensitive fields never reach the knowledge artifact, so a host that\n // builds its field list from it would silently drop the step that names\n // one. Keep help prose free of them.\n for (const ref of recipe.help.fieldRefs) {\n const found = findField(ref, models);\n if (\n found &&\n sensitiveByModel.get(found.model.name)?.has(found.field.name)\n ) {\n problems.push(\n `recipe ${recipe.id}: help: {field:${ref}} names a sensitive field; sensitive fields are excluded from the knowledge artifact, so describe it without a field reference`,\n );\n }\n }\n }\n if (problems.length > 0) {\n throw new Error(\n `[manifest-generator] invalid recipe help:\\n ${problems.join('\\n ')}`,\n );\n }\n }\n\n /**\n * Validate every `decoratorConfig.previousQualifiedNames` declaration\n * (#3338). The declaration rides into the manifest verbatim — it is the\n * lazy loader's alias index — so a malformed or colliding alias must stop\n * the build rather than ship a manifest the runtime will refuse:\n *\n * - an array of scoped `@scope/package:ClassName` strings, each listed once;\n * - never the object's own qualified name, nor any object of this manifest;\n * - never declared by two objects of this manifest.\n */\n assertQualifiedNameAliases(manifest: SmartObjectManifest): void {\n const ownNames = new Set<string>();\n for (const [key, obj] of Object.entries(manifest.objects)) {\n ownNames.add(obj.qualifiedName ?? key);\n }\n const claimedBy = new Map<string, string>();\n for (const key of Object.keys(manifest.objects).sort(compareText)) {\n const obj = manifest.objects[key];\n const owner = obj.qualifiedName ?? key;\n const declared = (\n obj.decoratorConfig as { previousQualifiedNames?: unknown } | undefined\n )?.previousQualifiedNames;\n if (declared === undefined) continue;\n if (!Array.isArray(declared)) {\n throw new Error(\n `[manifest-generator] ${owner}: previousQualifiedNames must be an array of qualified names (\"@package/name:ClassName\").`,\n );\n }\n const aliases = readPreviousQualifiedNames(obj.decoratorConfig);\n if (aliases.length !== declared.length) {\n throw new Error(\n `[manifest-generator] ${owner}: previousQualifiedNames must contain only string literals.`,\n );\n }\n const seen = new Set<string>();\n for (const alias of aliases) {\n if (!isQualifiedNameAliasFormat(alias)) {\n throw new Error(\n `[manifest-generator] ${owner}: previousQualifiedNames entry \"${alias}\" is not a qualified name (\"@package/name:ClassName\").`,\n );\n }\n if (seen.has(alias)) {\n throw new Error(\n `[manifest-generator] ${owner}: previousQualifiedNames lists \"${alias}\" more than once.`,\n );\n }\n seen.add(alias);\n if (ownNames.has(alias)) {\n throw new Error(\n `[manifest-generator] ${owner}: previousQualifiedNames \"${alias}\" names a live object of this package; an alias may only name a class that no longer exists.`,\n );\n }\n const other = claimedBy.get(alias);\n if (other) {\n throw new Error(\n `[manifest-generator] previousQualifiedNames \"${alias}\" is declared by both ${other} and ${owner}; an old name can resolve to only one class.`,\n );\n }\n claimedBy.set(alias, owner);\n }\n }\n }\n\n /**\n * Validate and resolve presentation metadata (#3599), failing the build on\n * a declaration no host could honor:\n *\n * - `@field({ ui: { widget } })` must name a known widget the field's type\n * accepts (every widget is text-only; `currency` is an ISO 4217 code\n * picker, not an amount).\n * - `@smrt({ display: { label } })` must name an own, non-sensitive,\n * non-transient, non-relationship field.\n * - A selector slot's `selects` must resolve when it names this package.\n *\n * Also stamps each object's resolved `displayLabelField` (the declared field,\n * else the first of name/title/label/code).\n */\n applyUiMetadata(manifest: SmartObjectManifest): void {\n const failures: string[] = [];\n\n for (const key of Object.keys(manifest.objects).sort(compareText)) {\n const obj = manifest.objects[key];\n const owner = obj.qualifiedName ?? key;\n\n for (const [fieldName, field] of Object.entries(obj.fields)) {\n const role = (field._meta as { role?: unknown } | undefined)?.role;\n if (role !== undefined) {\n if (!isRelationshipRole(role)) {\n failures.push(\n `${owner}.${fieldName}: role ${JSON.stringify(role)} is not one of ${RELATIONSHIP_ROLES.join(', ')}.`,\n );\n } else if (\n field.type !== 'foreignKey' &&\n field.type !== 'crossPackageRef'\n ) {\n failures.push(\n `${owner}.${fieldName}: role \"${role}\" needs a foreignKey or crossPackageRef field, but this field is ${field.type}.`,\n );\n }\n }\n const ui = field._meta?.ui as\n | { widget?: unknown; format?: unknown }\n | undefined;\n if (!ui || typeof ui !== 'object') continue;\n if (ui.format !== undefined) {\n if (!isFieldUIFormat(ui.format)) {\n failures.push(\n `${owner}.${fieldName}: ui.format ${JSON.stringify(ui.format)} is not one of ${FIELD_UI_FORMATS.join(', ')}.`,\n );\n } else if (!FIELD_UI_FORMAT_TYPES[ui.format].includes(field.type)) {\n failures.push(\n `${owner}.${fieldName}: ui.format \"${ui.format}\" needs a field of type ${FIELD_UI_FORMAT_TYPES[ui.format].join(' or ')}, but this field is ${field.type}.`,\n );\n }\n }\n if (ui.widget === undefined) continue;\n if (!isFieldUIWidget(ui.widget)) {\n failures.push(\n `${owner}.${fieldName}: ui.widget ${JSON.stringify(ui.widget)} is not one of ${FIELD_UI_WIDGETS.join(', ')}.`,\n );\n } else if (!FIELD_UI_WIDGET_TYPES[ui.widget].includes(field.type)) {\n failures.push(\n `${owner}.${fieldName}: ui.widget \"${ui.widget}\" needs a field of type ${FIELD_UI_WIDGET_TYPES[ui.widget].join(' or ')}, but this field is ${field.type}.`,\n );\n }\n }\n\n const display = (obj.decoratorConfig as { display?: unknown } | undefined)\n ?.display;\n let declared: string | undefined;\n if (display !== undefined) {\n const label =\n display && typeof display === 'object'\n ? (display as { label?: unknown }).label\n : undefined;\n if (\n label !== undefined &&\n (typeof label !== 'string' || label === '')\n ) {\n failures.push(\n `${owner}: display.label must be the name of an own field (a string literal), not ${JSON.stringify(label)}.`,\n );\n } else if (typeof label === 'string') {\n const problem = displayLabelFieldProblem(obj.fields, label);\n if (problem) {\n failures.push(\n `${owner}: display.label \"${label}\" cannot label a record: ${problem}.`,\n );\n } else {\n declared = label;\n }\n } else if (display === null || typeof display !== 'object') {\n failures.push(`${owner}: display must be an object ({ label }).`);\n }\n }\n const resolved = resolveDisplayLabelField(obj.fields, declared);\n if (resolved) {\n obj.displayLabelField = resolved;\n } else {\n delete obj.displayLabelField;\n }\n }\n\n const own = new Set<string>();\n for (const [key, obj] of Object.entries(manifest.objects)) {\n own.add(obj.qualifiedName ?? key);\n }\n for (const [slotId, selector] of Object.entries(\n manifest.uiSelectors ?? {},\n )) {\n const target = selector.selects;\n const targetPackage = target.slice(0, target.indexOf(':'));\n if (\n manifest.packageName &&\n targetPackage === manifest.packageName &&\n !own.has(target)\n ) {\n failures.push(\n `UI slot \"${slotId}\" selects ${target}, which is not an object of ${manifest.packageName}.`,\n );\n }\n }\n\n if (failures.length > 0) {\n throw new Error(\n `UI metadata invalid:\\n${failures.map((f) => ` - ${f}`).join('\\n')}`,\n );\n }\n }\n\n assertTenantScopedSchemaContract(manifest: SmartObjectManifest): void {\n const failures: string[] = [];\n\n for (const objectDef of Object.values(manifest.objects)) {\n const tenantScoped = objectDef.decoratorConfig?.tenantScoped;\n if (!tenantScoped) {\n continue;\n }\n\n const { tenantConfig } = this.normalizeTenantScopedConfig(tenantScoped);\n const fieldName = tenantConfig.field;\n const columnName = toSnakeCase(fieldName);\n\n if (!objectDef.fields[fieldName]) {\n failures.push(\n `${objectDef.className}: missing tenant-scoped field \"${fieldName}\"`,\n );\n continue;\n }\n\n const fieldTypeFailure = this.getTenantScopedFieldTypeFailure(\n objectDef,\n fieldName,\n );\n if (fieldTypeFailure) {\n failures.push(fieldTypeFailure);\n continue;\n }\n\n const schemaOwner = this.getTenantScopedSchemaOwner(objectDef, manifest);\n const schemaOwnerContext =\n schemaOwner === objectDef\n ? ''\n : ` on STI base \"${schemaOwner.className}\"`;\n\n if (!schemaOwner.schema?.columns) {\n failures.push(\n `${objectDef.className}: schema has not been generated for tenant-scoped column \"${columnName}\"${schemaOwnerContext}`,\n );\n continue;\n }\n\n if (!schemaOwner.schema.columns[columnName]) {\n failures.push(\n `${objectDef.className}: schema is missing tenant-scoped column \"${columnName}\"${schemaOwnerContext}`,\n );\n }\n }\n\n if (failures.length > 0) {\n throw new Error(\n `Tenant-scoped schema contract failed:\\n${failures\n .map((failure) => ` - ${failure}`)\n .join('\\n')}`,\n );\n }\n }\n\n private getTenantScopedSchemaOwner(\n objectDef: SmartObjectDefinition,\n manifest: SmartObjectManifest,\n ): SmartObjectDefinition {\n if (!this.isSTIChildClass(objectDef, manifest)) {\n return objectDef;\n }\n\n const stiBase = this.findSTIBaseInfo(objectDef, manifest);\n if (!stiBase) {\n return objectDef;\n }\n\n const localBase = Object.values(manifest.objects).find(\n (candidate) => candidate.className === stiBase.className,\n );\n\n return localBase ?? objectDef;\n }\n\n private getTenantScopedFieldTypeFailure(\n objectDef: SmartObjectDefinition,\n fieldName: string,\n ): string | undefined {\n const field = objectDef.fields[fieldName];\n if (!field) {\n return undefined;\n }\n\n if (field.type !== 'text' && field.type !== 'foreignKey') {\n return `${objectDef.className}: tenant-scoped field \"${fieldName}\" must use type \"text\" or \"foreignKey\"; received \"${field.type}\"`;\n }\n\n const sqlType = field._meta?.sqlType;\n if (sqlType && !['TEXT', 'UUID'].includes(String(sqlType).toUpperCase())) {\n return `${objectDef.className}: tenant-scoped field \"${fieldName}\" must use SQL type \"UUID\" or legacy \"TEXT\"; received \"${sqlType}\"`;\n }\n\n return undefined;\n }\n\n private normalizeTenantScopedConfig(tenantScoped: unknown): {\n tenantConfig: {\n mode: string;\n field: string;\n autoFilter: boolean;\n autoPopulate: boolean;\n allowSuperAdminBypass: boolean;\n };\n } {\n const tenantOptions: TenantScopedOptions =\n typeof tenantScoped === 'boolean'\n ? {}\n : (tenantScoped as TenantScopedOptions);\n\n return {\n tenantConfig: {\n mode: tenantOptions.mode ?? 'required',\n field: tenantOptions.field ?? 'tenantId',\n autoFilter: tenantOptions.autoFilter ?? true,\n autoPopulate: tenantOptions.autoPopulate ?? true,\n allowSuperAdminBypass: tenantOptions.allowSuperAdminBypass ?? false,\n },\n };\n }\n\n /**\n * Generate pre-computed validation rules for all objects in the manifest.\n *\n * This extracts validation constraints (required, min, max, minLength, maxLength, pattern)\n * from field definitions and stores them as serializable rules in the manifest.\n *\n * At runtime, these rules can be evaluated without creating validator closures,\n * significantly reducing CLI startup time for projects with many SMRT objects.\n *\n * @param manifest - The manifest to process in-place\n */\n generateValidationRules(manifest: SmartObjectManifest): void {\n for (const [name, obj] of Object.entries(manifest.objects)) {\n const rules: ValidationRule[] = [];\n let skippedAutoPopulatedTenantRequiredRule = false;\n\n for (const [fieldName, field] of Object.entries(obj.fields)) {\n // Skip transient fields (they're not persisted, so no validation needed)\n if (field.transient || field._meta?.transient) {\n continue;\n }\n\n const options = field._meta || {};\n\n // Required field rule\n const isAutoPopulatedTenantField =\n options.__tenancy?.isTenantIdField === true &&\n options.__tenancy.autoPopulate !== false;\n if (\n (options.required || field.required) &&\n !isAutoPopulatedTenantField\n ) {\n rules.push({\n field: fieldName,\n rule: 'required',\n fieldType: field.type,\n });\n } else if (\n isAutoPopulatedTenantField &&\n (options.required || field.required)\n ) {\n // Tenant IDs can be required in the manifest and database while still\n // being absent at this pre-interceptor validation stage. Tenancy's\n // beforeSave hook stamps them from the active context before writing.\n skippedAutoPopulatedTenantRequiredRule = true;\n }\n\n // Numeric range rules (for integer, decimal fields)\n if (field.type === 'integer' || field.type === 'decimal') {\n if (options.min !== undefined || field.min !== undefined) {\n rules.push({\n field: fieldName,\n rule: 'min',\n value: options.min ?? field.min,\n fieldType: field.type,\n });\n }\n\n if (options.max !== undefined || field.max !== undefined) {\n rules.push({\n field: fieldName,\n rule: 'max',\n value: options.max ?? field.max,\n fieldType: field.type,\n });\n }\n }\n\n // String length rules (for text fields)\n if (field.type === 'text') {\n if (\n options.minLength !== undefined ||\n field.minLength !== undefined\n ) {\n rules.push({\n field: fieldName,\n rule: 'minLength',\n value: options.minLength ?? field.minLength,\n fieldType: field.type,\n });\n }\n\n if (\n options.maxLength !== undefined ||\n field.maxLength !== undefined\n ) {\n rules.push({\n field: fieldName,\n rule: 'maxLength',\n value: options.maxLength ?? field.maxLength,\n fieldType: field.type,\n });\n }\n\n // Pattern rule (regex validation)\n // Note: Custom validator functions (options.validate) cannot be serialized\n // and will fall back to compiled validators at runtime\n // Note: Pattern is only available in field options, not in FieldDefinition\n const pattern = options.pattern;\n if (pattern) {\n rules.push({\n field: fieldName,\n rule: 'pattern',\n // RegExp patterns expose `.source`; a JSON-collapsed RegExp ({})\n // has none, preserving the prior `undefined` value exactly.\n value:\n typeof pattern === 'string'\n ? pattern\n : (pattern as { source?: string }).source,\n fieldType: field.type,\n });\n }\n }\n }\n\n // An explicit empty list is meaningful when the sole required field is\n // auto-populated by tenancy: it prevents runtime registration from\n // recompiling a pre-interceptor required validator for that field.\n if (rules.length > 0 || skippedAutoPopulatedTenantRequiredRule) {\n obj.validationRules = rules;\n }\n }\n }\n\n /**\n * Generate pre-computed schemas for all objects in the manifest.\n *\n * This enables external package consumers to use pre-generated schemas\n * without calling generateSchema() at runtime, eliminating latency.\n *\n * IMPORTANT: For STI classes, we aggregate ALL descendants from both local\n * and external packages to ensure complete schemas are generated.\n *\n * This method is public to allow external callers (like OXC scanner) to use it.\n *\n * @param manifest - The manifest to process in-place\n */\n generateSchemas(manifest: SmartObjectManifest): void {\n const generator = new SchemaGenerator();\n\n // Create aggregated manifest that includes external package objects\n // This ensures STI schema generation finds ALL descendants\n const aggregatedManifest = this.createAggregatedManifest(manifest);\n const schemaClasses = new Map(\n Object.values(aggregatedManifest.objects).map((obj) => [\n obj.className,\n obj,\n ]),\n );\n\n // An external class with the same simple name cannot replace a local item.\n for (const obj of Object.values(manifest.objects))\n schemaClasses.set(obj.className, obj);\n\n for (const [name, obj] of Object.entries(manifest.objects)) {\n // Collections access their item model's table; an independent schema can\n // contradict that model's tenant/conflict identity during aggregation.\n if (this.extendsCollection(obj, schemaClasses, aggregatedManifest)) {\n delete obj.schema;\n continue;\n }\n if (FRAMEWORK_ABSTRACT_BASE_NAMES.has(obj.className)) {\n continue;\n }\n\n // Determine table name (may have been inherited from external STI base)\n // Use obj.className (PascalCase) for consistent table name derivation with runtime\n const tableName =\n obj.decoratorConfig?.tableName ||\n this.classNameToTableName(obj.className);\n\n // Check if this is an STI class. `mergeInheritedFields()` copies the\n // base's `tableStrategy` onto every descendant, so both the root and\n // its children arrive here; `isSTIChildClass` covers a child whose\n // strategy was not inherited.\n if (\n obj.decoratorConfig?.tableStrategy === 'sti' ||\n this.isSTIChildClass(obj, manifest)\n ) {\n // Every class in an STI hierarchy — root, local child, or a child of\n // an EXTERNAL base — carries the schema of the ONE shared table,\n // generated from the ROOT base so descendant discovery, the\n // discriminator-partial unique indexes and the base-declared /\n // descendant-declared distinction are computed against the same\n // hierarchy on every class (#527, #2359). A child generated as if it\n // were the root would treat its own descendant-only `unique: true`\n // fields as base-declared and emit a full unique index that\n // `getAllSchemasAsDefinitions()` then merges into the table beside\n // the correct partial one.\n const stiRoot = this.findSTIBaseInfo(obj, manifest);\n const rootKey = stiRoot\n ? (this.resolveManifestKey(stiRoot.className, aggregatedManifest) ??\n stiRoot.className)\n : name;\n const rootTableName = stiRoot?.tableName || tableName;\n const rootConfig =\n aggregatedManifest.objects[rootKey]?.decoratorConfig ??\n obj.decoratorConfig;\n\n logger.debug(\n `[manifest-generator] Generating STI schema for ${name} (root: ${rootKey}, table: ${rootTableName})`,\n );\n\n // Use aggregated manifest to find descendants from ALL packages\n obj.schema = generator.generateSTISchemaFromManifest(\n rootKey,\n rootTableName,\n obj.fields,\n aggregatedManifest,\n rootConfig,\n );\n this.applySqlTypeOverrides(obj);\n } else {\n // CTI class - generate individual table schema\n logger.debug(\n `[manifest-generator] Generating CTI schema for ${name} (table: ${tableName})`,\n );\n\n obj.schema = generator.generateCTISchemaFromManifest(\n name,\n tableName,\n obj.fields,\n obj.decoratorConfig,\n );\n this.applySqlTypeOverrides(obj);\n }\n }\n\n this.resolveSamePackageForeignKeyColumnTypes(manifest, generator);\n\n // Preserve collection metadata, but take persistence identity from the item\n // model only after every model schema (including FK repair) is complete.\n for (const obj of Object.values(manifest.objects)) {\n if (!this.extendsCollection(obj, schemaClasses, aggregatedManifest))\n continue;\n let current: SmartObjectDefinition | undefined = obj;\n const visited = new Set<SmartObjectDefinition>();\n while (current && !visited.has(current)) {\n visited.add(current);\n const item = this.findItemClass(\n current,\n aggregatedManifest,\n schemaClasses,\n );\n if (\n item?.schema &&\n !this.extendsCollection(item, schemaClasses, aggregatedManifest)\n ) {\n obj.schema = structuredClone(item.schema);\n break;\n }\n current = this.namedParent(current, schemaClasses, aggregatedManifest);\n }\n }\n }\n\n /** A report model's generated surface defaults to `list`/`get`. */\n applyReportSurfaceDefaults(manifest: SmartObjectManifest): void {\n for (const obj of Object.values(manifest.objects)) {\n if (!obj.decoratorConfig?.report) continue;\n obj.decoratorConfig.api ??= { include: ['list', 'get'] };\n obj.decoratorConfig.mcp ??= { include: ['list', 'get'] };\n }\n }\n\n normalizeReportObjects(manifest: SmartObjectManifest): void {\n this.applyReportSurfaceDefaults(manifest);\n for (const obj of Object.values(manifest.objects)) {\n if (!obj.decoratorConfig?.report) continue;\n\n if (obj.decoratorConfig.conflictColumns) continue;\n\n const tenantScoped = obj.decoratorConfig.tenantScoped;\n const tenantField =\n tenantScoped && typeof tenantScoped === 'object'\n ? tenantScoped.field || 'tenantId'\n : tenantScoped\n ? 'tenantId'\n : undefined;\n const tenantColumn =\n tenantField && obj.fields[tenantField] ? toSnakeCase(tenantField) : '';\n\n const conflictColumns = Object.entries(obj.fields)\n .filter(([, field]) => {\n const kind = field._meta?.__report?.kind;\n return kind === 'group' || kind === 'bucket';\n })\n .map(([fieldName]) => toSnakeCase(fieldName));\n\n obj.decoratorConfig.conflictColumns =\n conflictColumns.length > 0\n ? [...(tenantColumn ? [tenantColumn] : []), ...conflictColumns]\n : ['id'];\n }\n }\n\n normalizeReportTenantScope(manifest: SmartObjectManifest): void {\n for (const obj of Object.values(manifest.objects)) {\n if (!obj.decoratorConfig?.report) continue;\n obj.decoratorConfig.tenantScoped ??= { mode: 'optional' };\n }\n }\n\n /**\n * Materialize the tenant-aware default conflict target (#2360).\n *\n * A tenant-owned class — tenant-scoped, or carrying an undeclared\n * `tenantId` field (`resolveOwnershipTenantColumn()`) — that declares no\n * `@smrt({ conflictColumns })` keys on `[tenant column, ...natural key]` — `(tenant_id, slug, context)` for\n * a class-per-table object, `(tenant_id, slug, context, _meta_type)` for a\n * single-table hierarchy — so two tenants can each own the same slug and\n * neither `save()` adopts the other's row. Writing the resolved key into\n * `decoratorConfig.conflictColumns` (mirroring `normalizeReportObjects`)\n * makes the manifest, the generated schema, the knowledge artifact and\n * `ObjectRegistry.getConflictColumns()` read one value.\n *\n * Only schema owners are normalized: an STI child inherits the table (and\n * therefore the key) from its root, and `getConflictColumns()` resolves a\n * child through its root at runtime. Explicit `conflictColumns` and\n * `@report` classes (keyed by `normalizeReportObjects`) are left alone.\n * Runs after `injectTenantScopedFields()` and `mergeInheritedFields()` so\n * the tenant field and the inherited `tableStrategy` are in place, and\n * before `generateSchemas()`.\n */\n normalizeConflictColumns(manifest: SmartObjectManifest): void {\n for (const obj of Object.values(manifest.objects)) {\n if (!obj.decoratorConfig) continue;\n if (FRAMEWORK_ABSTRACT_BASE_NAMES.has(obj.className)) continue;\n if (obj.decoratorConfig.conflictColumns) continue;\n if (obj.decoratorConfig.report) continue;\n if (this.isSTIChildClass(obj, manifest)) continue;\n\n const tenantScoped = obj.decoratorConfig.tenantScoped;\n const declaredTenantColumn = tenantScoped\n ? resolveTenantColumn(\n this.normalizeTenantScopedConfig(tenantScoped).tenantConfig.field,\n (fieldName) => Boolean(obj.fields[fieldName]),\n toSnakeCase,\n )\n : undefined;\n // A class that carries `tenantId` without declaring tenancy (a consumer\n // registers it with the tenancy interceptor at runtime) is still\n // tenant-OWNED: its natural key is unique per tenant too.\n const tenantColumn = resolveOwnershipTenantColumn(\n declaredTenantColumn,\n (column) =>\n Object.keys(obj.fields).some(\n (fieldName) => toSnakeCase(fieldName) === column,\n ),\n );\n if (!tenantColumn) continue;\n\n obj.decoratorConfig.conflictColumns = defaultConflictColumns(\n obj.decoratorConfig.tableStrategy === 'sti' ? 'sti' : 'cti',\n tenantColumn,\n );\n }\n }\n\n private resolveSamePackageForeignKeyColumnTypes(\n manifest: SmartObjectManifest,\n generator: SchemaGeneratorLike,\n ): void {\n // One representative schema per table for target-id lookups, plus EVERY\n // schema that describes a table: each class of an STI hierarchy carries a\n // copy of the shared table's schema (#2359), and every copy must receive\n // the same reconciled type or `getAllSchemasAsDefinitions()`'s\n // first-wins column merge can surface an unreconciled one.\n const schemaByTable = new Map<string, ManifestSchema>();\n const schemasByTable = new Map<string, ManifestSchema[]>();\n const ownerBySchema = new Map<\n ManifestSchema,\n { name: string; obj: SmartObjectDefinition }\n >();\n const changedSchemas = new Set<ManifestSchema>();\n const objectsByName = new Map<string, SmartObjectDefinition>();\n\n for (const [name, obj] of Object.entries(manifest.objects)) {\n objectsByName.set(obj.className, obj);\n objectsByName.set(obj.className.toLowerCase(), obj);\n if (obj.schema?.tableName) {\n schemaByTable.set(obj.schema.tableName, obj.schema);\n const siblings = schemasByTable.get(obj.schema.tableName) ?? [];\n siblings.push(obj.schema);\n schemasByTable.set(obj.schema.tableName, siblings);\n ownerBySchema.set(obj.schema, { name, obj });\n }\n }\n\n for (const obj of Object.values(manifest.objects)) {\n const sourceTable = this.getObjectTableName(obj);\n if (!sourceTable) {\n continue;\n }\n\n const sourceSchemas = schemasByTable.get(sourceTable);\n if (!sourceSchemas || sourceSchemas.length === 0) {\n continue;\n }\n\n for (const [fieldName, field] of Object.entries(obj.fields || {})) {\n if (\n field.type !== 'foreignKey' ||\n !field.related ||\n field._meta?.__tenancy?.isTenantIdField === true\n ) {\n continue;\n }\n\n const emitConstraint = field._meta?.constraint !== false;\n\n const columnName = toSnakeCase(fieldName);\n const targetSchema = this.findForeignKeyTargetSchema(\n field.related,\n manifest,\n schemaByTable,\n obj.packageName,\n );\n if (!targetSchema) {\n for (const sourceSchema of sourceSchemas) {\n const sourceColumn = sourceSchema.columns[columnName];\n if (sourceColumn?.foreignKey) {\n sourceSchema.columns[columnName] = {\n ...sourceColumn,\n foreignKey: undefined,\n };\n changedSchemas.add(sourceSchema);\n }\n }\n continue;\n }\n\n const [, declaredTargetColumn] = field.related.split('.');\n const targetColumn =\n declaredTargetColumn ||\n Object.entries(targetSchema.columns).find(\n ([, definition]) => definition.primaryKey === true,\n )?.[0] ||\n 'id';\n const targetIdType = targetSchema.columns[targetColumn]?.type;\n const conflictOwner =\n this.findSTIBase(obj, objectsByName, manifest) ?? obj;\n const conflictColumns = new Set(\n (conflictOwner.decoratorConfig?.conflictColumns || []).map((column) =>\n toSnakeCase(column),\n ),\n );\n const { action } = resolveForeignKeyDeleteAction({\n declared: field._meta?.onDelete,\n isConflictColumn: conflictColumns.has(columnName),\n isTenantIdField: false,\n columnName,\n });\n\n for (const sourceSchema of sourceSchemas) {\n const sourceColumn = sourceSchema.columns[columnName];\n if (!sourceColumn) {\n continue;\n }\n const nextColumn = {\n ...sourceColumn,\n ...(!field._meta?.sqlType && targetIdType\n ? { type: targetIdType }\n : {}),\n foreignKey: emitConstraint\n ? {\n table: targetSchema.tableName,\n column: targetColumn,\n onDelete: action,\n onUpdate: resolveForeignKeyUpdateAction(\n field._meta?.onUpdate,\n ),\n ...(typeof field._meta?.constraint === 'object'\n ? { engines: [...field._meta.constraint.engines] }\n : {}),\n }\n : undefined,\n };\n if (JSON.stringify(nextColumn) === JSON.stringify(sourceColumn)) {\n continue;\n }\n sourceSchema.columns[columnName] = nextColumn;\n changedSchemas.add(sourceSchema);\n }\n }\n }\n\n for (const schema of changedSchemas) {\n this.refreshManifestSchemaDDL(\n schema,\n generator,\n ownerBySchema.get(schema),\n manifest,\n );\n }\n }\n\n private findForeignKeyTargetSchema(\n related: string,\n manifest: SmartObjectManifest,\n schemaByTable: Map<string, ManifestSchema>,\n sourcePackageName?: string,\n ): ManifestSchema | undefined {\n const relatedTarget = related.split('.')[0];\n if (schemaByTable.has(relatedTarget)) {\n return schemaByTable.get(relatedTarget);\n }\n\n const candidates = Object.values(manifest.objects).filter(\n (candidate) =>\n candidate.className === relatedTarget ||\n candidate.qualifiedName === relatedTarget ||\n candidate.name === relatedTarget ||\n candidate.decoratorConfig?.tableName === relatedTarget ||\n candidate.schema?.tableName === relatedTarget,\n );\n const localTarget = candidates.find(\n (candidate) => candidate.packageName === sourcePackageName,\n );\n if (!localTarget && candidates.length > 1) {\n throw new Error(\n `Ambiguous foreign key target ${relatedTarget} from package ${sourcePackageName}`,\n );\n }\n const targetObj = localTarget ?? candidates[0];\n\n if (!targetObj && relatedTarget.includes(':')) {\n return undefined;\n }\n\n const targetTable = targetObj\n ? this.getObjectTableName(targetObj)\n : this.classNameToTableName(relatedTarget);\n\n return targetTable ? schemaByTable.get(targetTable) : undefined;\n }\n\n private getObjectTableName(obj: SmartObjectDefinition): string | undefined {\n return (\n obj.schema?.tableName ||\n obj.decoratorConfig?.tableName ||\n this.classNameToTableName(obj.className)\n );\n }\n\n private refreshManifestSchemaDDL(\n schema: ManifestSchema,\n generator: SchemaGeneratorLike,\n owner: { name: string; obj: SmartObjectDefinition } | undefined,\n manifest: SmartObjectManifest,\n ): void {\n const columns: Record<string, ColumnDefinition> = {};\n for (const [name, column] of Object.entries(schema.columns)) {\n columns[name] = {\n // ManifestColumnDefinition stores `type` as a plain string; it is\n // always a valid SQLDataType for DDL rendering.\n type: column.type as SQLDataType,\n primaryKey: column.primaryKey,\n notNull: column.notNull,\n unique: column.unique,\n defaultValue: column.default,\n foreignKey: column.foreignKey ? { ...column.foreignKey } : undefined,\n };\n }\n\n const schemaDefinition: SchemaDefinition = {\n tableName: schema.tableName,\n columns,\n indexes: (schema.indexes || []).map((index) => ({\n name: index.name,\n columns: index.columns,\n unique: index.unique,\n ...(index.nullsNotDistinct ? { nullsNotDistinct: true } : {}),\n where: index.where,\n jsonPath: index.jsonPath,\n })),\n triggers: [],\n foreignKeys: Object.entries(columns).flatMap(([column, definition]) =>\n definition.foreignKey\n ? [\n {\n column,\n referencesTable: definition.foreignKey.table,\n referencesColumn: definition.foreignKey.column,\n onDelete: definition.foreignKey.onDelete,\n onUpdate: definition.foreignKey.onUpdate,\n ...(definition.foreignKey.engines\n ? { engines: definition.foreignKey.engines }\n : {}),\n },\n ]\n : [],\n ),\n dependencies: Object.values(columns)\n .flatMap((definition) =>\n definition.foreignKey ? [definition.foreignKey.table] : [],\n )\n .filter((dependency) => dependency !== schema.tableName),\n version: schema.version,\n packageName: '',\n };\n\n schema.ddl = generator.generateSQL(schemaDefinition);\n schema.version = this.computeManifestSchemaVersion(schema, owner, manifest);\n }\n\n private computeManifestSchemaVersion(\n schema: ManifestSchema,\n owner: { name: string; obj: SmartObjectDefinition } | undefined,\n manifest: SmartObjectManifest,\n ): string {\n if (schema.columns._meta_type && owner) {\n const baseClassName =\n owner.obj.decoratorConfig?.tableStrategy === 'sti'\n ? owner.name\n : this.findSTIBaseInfo(owner.obj, manifest)?.className || owner.name;\n\n return createHash('sha256')\n .update(\n JSON.stringify({\n columns: schema.columns,\n baseClassName,\n descendants: this.findDescendantsInManifest(\n baseClassName,\n manifest,\n ),\n }),\n )\n .digest('hex')\n .substring(0, 8);\n }\n\n return createHash('sha256')\n .update(\n JSON.stringify({\n columns: schema.columns,\n className: owner?.name || schema.tableName,\n }),\n )\n .digest('hex')\n .substring(0, 8);\n }\n\n private findDescendantsInManifest(\n baseClassName: string,\n manifest: SmartObjectManifest,\n visited: Set<string> = new Set(),\n ): string[] {\n const descendants: string[] = [];\n if (visited.has(baseClassName)) {\n return descendants;\n }\n visited.add(baseClassName);\n\n const baseClassLower = this.simpleClassName(baseClassName).toLowerCase();\n\n for (const [name, obj] of Object.entries(manifest.objects)) {\n const classNameLower = this.simpleClassName(obj.className).toLowerCase();\n const extendsLower = obj.extends\n ? this.simpleClassName(obj.extends).toLowerCase()\n : undefined;\n\n if (\n classNameLower === baseClassLower &&\n extendsLower === baseClassLower\n ) {\n continue;\n }\n\n // An import-qualified parent names its package: a same-named base of\n // another package is not this class's ancestor (#4145).\n if (\n extendsLower === baseClassLower &&\n !this.qualifiedParentExcludes(obj, baseClassName)\n ) {\n descendants.push(name);\n descendants.push(\n ...this.findDescendantsInManifest(name, manifest, visited),\n );\n }\n }\n\n return descendants;\n }\n\n /**\n * Whether `obj`'s import-qualified parent rules out `baseClassName` (a\n * qualified name of another class with the same simple name).\n */\n private qualifiedParentExcludes(\n obj: SmartObjectDefinition,\n baseClassName: string,\n ): boolean {\n return (\n !!obj.extendsQualified &&\n isQualifiedName(baseClassName) &&\n obj.extendsQualified !== baseClassName\n );\n }\n\n private applySqlTypeOverrides(obj: SmartObjectDefinition): void {\n if (!obj.schema?.columns) {\n return;\n }\n\n for (const [fieldName, field] of Object.entries(obj.fields || {})) {\n const sqlType = field?._meta?.sqlType;\n const referenceKind = this.getReferenceKind(field);\n if (!sqlType && !referenceKind) {\n continue;\n }\n\n const columnName = toSnakeCase(fieldName);\n if (!obj.schema.columns[columnName]) {\n continue;\n }\n\n const column = {\n ...obj.schema.columns[columnName],\n ...(sqlType ? { type: String(sqlType).toUpperCase() } : {}),\n ...(referenceKind ? { referenceKind } : {}),\n };\n // A `''` initializer (e.g. `tenantId: string = ''`) is not a uuid: as a\n // column default PostgreSQL stores `(''::text)::uuid` unevaluated and\n // every INSERT that omits the column fails with 22P02. An identifier\n // column has no default.\n if (\n String(column.type).toUpperCase() === 'UUID' &&\n column.default === ''\n ) {\n delete column.default;\n }\n obj.schema.columns[columnName] = column;\n }\n }\n\n private getReferenceKind(\n field: SmartObjectDefinition['fields'][string] | undefined,\n ): ManifestColumnDefinition['referenceKind'] | undefined {\n if (field?._meta?.__tenancy?.isTenantIdField) {\n return 'tenantId';\n }\n\n if (field?.type === 'foreignKey') {\n return 'foreignKey';\n }\n\n if (field?.type === 'crossPackageRef') {\n return 'crossPackageRef';\n }\n\n return undefined;\n }\n\n /**\n * Create an aggregated manifest that includes objects from all external packages\n *\n * This is used for STI schema generation to ensure ALL descendants are found,\n * regardless of which package they're defined in.\n *\n * @param manifest - The local manifest\n * @returns Aggregated manifest with local + external objects\n */\n private createAggregatedManifest(\n manifest: SmartObjectManifest,\n ): SmartObjectManifest {\n // Start with a copy of local objects\n const aggregatedObjects: Record<string, SmartObjectDefinition> = {\n ...manifest.objects,\n };\n\n // Load and merge external package objects\n if (manifest.smrtDependencies && manifest.smrtDependencies.length > 0) {\n for (const packageName of manifest.smrtDependencies) {\n const externalManifest = loadExternalManifestSync(packageName);\n if (externalManifest) {\n // Merge external objects (local objects take precedence on collision)\n for (const [name, obj] of Object.entries(externalManifest.objects)) {\n if (!aggregatedObjects[name]) {\n aggregatedObjects[name] = obj;\n }\n }\n\n logger.debug(\n `[manifest-generator] Aggregated ${Object.keys(externalManifest.objects).length} objects from ${packageName}`,\n );\n }\n }\n }\n\n return {\n ...manifest,\n objects: aggregatedObjects,\n };\n }\n\n /**\n * Check if an object is an STI child class (inherits from STI base)\n *\n * Walks up the inheritance chain to find if any ancestor has tableStrategy: 'sti'.\n * Also checks external SMRT packages for parent class definitions.\n */\n private isSTIChildClass(\n obj: SmartObjectDefinition,\n manifest: SmartObjectManifest,\n ): boolean {\n if (!obj.extends) return false;\n\n // Build a lookup map for efficient access\n const objectsByName = new Map<string, SmartObjectDefinition>();\n for (const [_name, objDef] of Object.entries(manifest.objects)) {\n objectsByName.set(objDef.className, objDef);\n objectsByName.set(objDef.className.toLowerCase(), objDef);\n }\n\n // Walk up the inheritance chain looking for STI base\n let currentClass: string | undefined = this.parentRef(obj);\n const visited = new Set<string>();\n\n while (currentClass) {\n if (visited.has(currentClass)) break;\n visited.add(currentClass);\n\n // Local first, then external SMRT packages; a qualified parent only\n // resolves to its own package's class (#4145).\n const parentObj = this.resolveParentDefinition(\n currentClass,\n obj,\n manifest,\n objectsByName,\n );\n\n if (!parentObj) break; // Parent not found anywhere (e.g., SmrtObject)\n\n if (parentObj.decoratorConfig?.tableStrategy === 'sti') {\n return true; // Found STI ancestor\n }\n\n currentClass = this.parentRef(parentObj);\n }\n\n return false;\n }\n\n /**\n * Resolve a class name (simple `Content` or qualified `@pkg:Content`) to\n * the key it is stored under in `manifest.objects`, or `undefined` when the\n * manifest does not carry it. Manifest keys are qualified names; `extends`\n * and {@link findSTIBaseInfo} report simple names.\n */\n private resolveManifestKey(\n className: string,\n manifest: SmartObjectManifest,\n ): string | undefined {\n if (manifest.objects[className]) return className;\n const simpleName = className.includes(':')\n ? className.slice(className.lastIndexOf(':') + 1)\n : className;\n for (const [key, obj] of Object.entries(manifest.objects)) {\n if (obj.qualifiedName === className || obj.className === simpleName) {\n return key;\n }\n }\n return undefined;\n }\n\n /**\n * Find full STI base class info (className + tableName)\n *\n * Walks up the inheritance chain to find the STI base class and returns\n * both its className and tableName. This is critical for external STI bases\n * where the child needs to use the base's table name for schema generation.\n */\n private findSTIBaseInfo(\n obj: SmartObjectDefinition,\n manifest: SmartObjectManifest,\n ): { className: string; tableName: string } | undefined {\n if (!obj.extends) return undefined;\n\n // Build a lookup map for efficient access\n const objectsByName = new Map<string, SmartObjectDefinition>();\n for (const [_name, objDef] of Object.entries(manifest.objects)) {\n objectsByName.set(objDef.className, objDef);\n objectsByName.set(objDef.className.toLowerCase(), objDef);\n }\n\n // Track the oldest STI base found as we walk up\n // (we need to keep walking to find the ROOT STI class, not the first one)\n let stiBaseInfo: { className: string; tableName: string } | undefined;\n\n // Walk up the inheritance chain looking for the OLDEST STI base\n let currentClass: string | undefined = this.parentRef(obj);\n const visited = new Set<string>();\n\n while (currentClass) {\n if (visited.has(currentClass)) break;\n visited.add(currentClass);\n\n const parentObj = this.resolveParentDefinition(\n currentClass,\n obj,\n manifest,\n objectsByName,\n );\n\n if (!parentObj) break;\n\n if (parentObj.decoratorConfig?.tableStrategy === 'sti') {\n // Found an STI ancestor - it becomes the new candidate base\n // Keep walking to find the OLDEST/ROOT STI class in the hierarchy\n const tableName =\n parentObj.decoratorConfig?.tableName ||\n parentObj.schema?.tableName ||\n this.classNameToTableName(parentObj.className);\n stiBaseInfo = {\n className: parentObj.className,\n tableName,\n };\n }\n\n currentClass = this.parentRef(parentObj);\n }\n\n return stiBaseInfo; // Return the oldest STI ancestor found (or undefined if none)\n }\n\n /**\n * Convert class name to table name (snake_case pluralized)\n *\n * IMPORTANT: Must use the same algorithm as runtime's tableNameFromClass()\n * to ensure manifest-generated table names match runtime-derived names.\n */\n private classNameToTableName(className: string): string {\n // Use the shared pluralization function that handles English plurals correctly\n // (e.g., 'Currency' → 'currencies', 'JournalEntry' → 'journal_entries')\n return classnameToTablename(className);\n }\n\n private normalizeFrameworkInheritedField(\n ancestorName: string,\n fieldName: string,\n fieldDef: FieldDefinition,\n childClassName: string,\n ): FieldDefinition {\n if (\n this.simpleClassName(ancestorName) === 'SmrtHierarchical' &&\n fieldName === 'parentId'\n ) {\n return {\n ...fieldDef,\n type: 'foreignKey',\n related: childClassName,\n required: false,\n _meta: {\n ...(fieldDef._meta || {}),\n nullable: true,\n },\n };\n }\n\n return fieldDef;\n }\n\n private simpleClassName(className: string): string {\n return className.includes(':')\n ? className.split(':').pop() || className\n : className;\n }\n\n /**\n * Merge inherited fields into child classes (build-time inheritance resolution)\n *\n * For STI hierarchies, child classes don't define their own fields in source code\n * (they inherit from parent). This method merges parent fields into child manifests\n * so that runtime code doesn't need to do field resolution.\n *\n * Also handles collection classes (SmrtCollection<T>) that should inherit their\n * item class's tableName and collection when the item uses STI.\n *\n * Handles multi-level inheritance (grandparents, great-grandparents, etc.)\n * Automatically loads parent class definitions from external SMRT packages when needed\n *\n * @param manifest - The manifest to process in-place\n */\n public mergeInheritedFields(manifest: SmartObjectManifest): void {\n // Build a map of className -> objectDef for fast lookup\n const objectsByName = new Map<string, SmartObjectDefinition>();\n for (const [name, obj] of Object.entries(manifest.objects)) {\n objectsByName.set(obj.className, obj);\n // Also store by lowercase name for case-insensitive lookup\n objectsByName.set(obj.className.toLowerCase(), obj);\n }\n\n // FIRST PASS: Handle STI field merging and tableName inheritance\n // This must happen FIRST so that item classes (like Meeting) have their tableName\n // inherited from their STI base (like Event) before collection classes (like Meetings)\n // try to read it\n for (const obj of Object.values(manifest.objects)) {\n if (!obj.extends) continue; // No parent, skip\n\n // Always walk the chain below — fields and methods now have\n // independent merge rules (#2624):\n // FIELDS merge when ANY of:\n // (a) STI is in play — shared table with parent, full chain\n // merges.\n // (b) An ancestor in the chain is a framework abstract base class\n // (SmrtHierarchical, SmrtJunction, …) — those have no table of\n // their own, so structural fields they declare (e.g.\n // `SmrtHierarchical.parentId`) must propagate into every CTI\n // subclass's manifest, otherwise WHERE-clause validation\n // rejects queries against the inherited column.\n // For plain CTI through a user-defined base with its own table,\n // field merging is skipped per-ancestor below — each class keeps\n // its own table layout.\n // METHODS merge from every ancestor except framework base classes,\n // independent of STI/CTI — a concrete decorated ancestor's public\n // methods are real inherited API regardless of table strategy.\n // There is no early exit here for a \"plain CTI through a\n // user-defined base\" class: that is exactly the case whose\n // methods previously went unmerged (the under-report half of\n // #2624).\n const usesSTI = this.isSTIClass(obj, objectsByName, manifest);\n\n logger.debug(\n `[manifest-generator] Merging inherited fields for ${obj.className} from ${obj.extends}`,\n );\n\n // Build full inheritance chain (base -> child). Each ancestor keeps\n // the definition it resolved to: re-resolving its simple name later\n // could pick another package's same-named class (#4145).\n const inheritanceChain: string[] = [];\n const ancestorDefs: Array<SmartObjectDefinition | undefined> = [];\n let currentClass: string | undefined = this.parentRef(obj);\n const visited = new Set<string>();\n\n while (currentClass) {\n if (visited.has(currentClass)) {\n logger.warn(\n `[manifest-generator] Circular inheritance detected for ${obj.className}`,\n );\n break;\n }\n visited.add(currentClass);\n\n // Skips self-reference: when a local class has the same name as its\n // imported parent (e.g., local Performer extends external Performer),\n // the local lookup returns the child itself and falls through to the\n // external package lookup.\n const parentObj = this.resolveParentDefinition(\n currentClass,\n obj,\n manifest,\n objectsByName,\n );\n\n // Chain entries are simple names, as before; the resolved definition\n // rides alongside.\n const ancestorName = this.simpleClassName(currentClass);\n inheritanceChain.unshift(ancestorName); // Add to front (building base -> child)\n ancestorDefs.unshift(parentObj);\n if (!parentObj) break; // Parent not found anywhere (e.g., SmrtObject)\n currentClass = this.parentRef(parentObj);\n }\n\n logger.debug(\n `[manifest-generator] Inheritance chain for ${obj.className}: ${inheritanceChain.join(' -> ')}`,\n );\n\n // Merge fields from ancestors (base to child).\n //\n // STI path: pull in fields from every ancestor — they all share one\n // table.\n //\n // Non-STI (framework-base) path: pull in fields ONLY from framework\n // abstract bases (SmrtHierarchical, …). User-defined ancestors with\n // their own `@smrt()` decorator have their own tables in CTI, so\n // merging their columns onto a descendant would generate the wrong\n // schema.\n const mergedFields: Record<string, FieldDefinition> = {};\n const mergedFieldOwners = new Map<string, string>();\n const mergedMethods: Record<string, MethodDefinition> = {};\n\n for (const [index, ancestorName] of inheritanceChain.entries()) {\n const ancestor = ancestorDefs[index];\n if (!ancestor) continue;\n\n const ancestorIsFrameworkBase =\n FRAMEWORK_ABSTRACT_BASE_NAMES.has(ancestorName);\n\n // FIELDS: STI subclasses share one table, so every ancestor's\n // columns are needed. CTI subclasses pull fields only from framework\n // abstract bases — a concrete `@smrt()` ancestor has its own table,\n // so merging its columns here would generate the wrong schema.\n if (usesSTI || ancestorIsFrameworkBase) {\n // Keep the oldest concrete STI declaration, but let a concrete\n // class replace a framework abstract default. For example, Event\n // refines SmrtHierarchical.parentId with its relationship target\n // and an engine-scoped physical constraint. The local child's own\n // fields are still applied after this loop.\n for (const [fieldName, fieldDef] of Object.entries(ancestor.fields)) {\n const existingOwner = mergedFieldOwners.get(fieldName);\n const replacesFrameworkDefault =\n existingOwner !== undefined &&\n FRAMEWORK_ABSTRACT_BASE_NAMES.has(\n this.simpleClassName(existingOwner),\n ) &&\n !FRAMEWORK_ABSTRACT_BASE_NAMES.has(\n this.simpleClassName(ancestorName),\n );\n if (!existingOwner || replacesFrameworkDefault) {\n mergedFields[fieldName] = this.normalizeFrameworkInheritedField(\n ancestorName,\n fieldName,\n fieldDef,\n obj.className,\n );\n mergedFieldOwners.set(fieldName, ancestorName);\n }\n }\n }\n\n // METHODS (#2624): methods are not columns and never needed the\n // STI/CTI field rule above — they inherited it only by sharing the\n // loop. Give them their own rule instead: merge from every ancestor\n // except the universal object/collection primitives in\n // FRAMEWORK_METHOD_BASE_NAMES (see its doc comment — deliberately\n // narrower than FRAMEWORK_ABSTRACT_BASE_NAMES), independent of\n // `usesSTI`. This both stops STI subclasses from absorbing\n // `SmrtObject`/`SmrtClass`/`SmrtCollection` internals (over-merge)\n // and lets CTI subclasses inherit a concrete decorated ancestor's\n // own public methods (under-merge), matching the runtime resolver's\n // `getAllMethods()` — while still letting a framework abstract\n // base's own intended API (e.g. SmrtJunction.attach/detach,\n // SmrtHierarchical.getChildren) merge in, the same way its fields\n // already do.\n //\n // Assignment is unconditional (not \"first ancestor wins\"): the\n // outer loop walks `inheritanceChain` base-to-child, so a later\n // (more-derived) ancestor's override must replace an earlier one —\n // e.g. a middle class that overrides a grandparent method. This\n // matches the runtime resolver's own `getAllMethods()`, which\n // walks the same base-to-child order and does a plain `Map.set()`\n // per ancestor for the identical reason (see its \"Child methods\n // override parent methods (no merging)\" comment). The child's own\n // methods still win over everything via the unconditional\n // \"Add child's own methods\" step below.\n if (!FRAMEWORK_METHOD_BASE_NAMES.has(ancestorName)) {\n for (const [methodName, methodDef] of Object.entries(\n ancestor.methods || {},\n )) {\n mergedMethods[methodName] = methodDef;\n }\n }\n }\n\n // Add child's own fields (override any parent fields with same name)\n for (const [fieldName, fieldDef] of Object.entries(obj.fields)) {\n mergedFields[fieldName] = fieldDef;\n }\n\n // Add child's own methods\n for (const [methodName, methodDef] of Object.entries(obj.methods || {})) {\n mergedMethods[methodName] = methodDef;\n }\n\n // Update object definition with merged fields\n obj.fields = mergedFields;\n obj.methods = mergedMethods;\n\n // Share storage while allowing an explicit independent route collection.\n const stiBase = this.findSTIBase(obj, objectsByName, manifest);\n if (stiBase && stiBase !== obj) {\n // Determine the STI base's table name (explicit or derived from className)\n // Note: We don't use stiBase.collection as fallback because collection uses\n // lowercase-only format (e.g., 'querytestevents') while tableName needs\n // snake_case format (e.g., 'query_test_events')\n const baseTableName =\n stiBase.decoratorConfig?.tableName ||\n this.classNameToTableName(stiBase.className);\n\n if (\n (obj.decoratorConfig?.sensitive === true) !==\n (stiBase.decoratorConfig?.sensitive === true)\n ) {\n throw new ConfigurationError(\n `STI hierarchy ${stiBase.className} has mixed sensitivity; mark every class sensitive or use separate tables.`,\n 'CONFIG_STI_MIXED_SENSITIVITY',\n );\n }\n // Inherit tableName from STI base\n obj.decoratorConfig = obj.decoratorConfig || {};\n obj.decoratorConfig.tableName = baseTableName;\n logger.debug(\n `[manifest-generator] ${obj.className} inherits tableName: '${baseTableName}' from ${stiBase.className}`,\n );\n\n // Inherit tableStrategy from STI base (so runtime doesn't need to walk inheritance chain)\n if (stiBase.decoratorConfig?.tableStrategy) {\n obj.decoratorConfig.tableStrategy =\n stiBase.decoratorConfig.tableStrategy;\n logger.debug(\n `[manifest-generator] ${obj.className} inherits tableStrategy: '${stiBase.decoratorConfig.tableStrategy}' from ${stiBase.className}`,\n );\n }\n\n // Collection controls routes/permissions independently of shared storage.\n if (typeof obj.decoratorConfig.collection === 'string') {\n obj.collection = obj.decoratorConfig.collection;\n }\n // Preserve the inherited default when no collection was declared.\n if (\n !obj.decoratorConfig.collection &&\n stiBase.collection !== obj.collection\n ) {\n logger.debug(\n `[manifest-generator] ${obj.className} inherits collection: '${stiBase.collection}' from ${stiBase.className}`,\n );\n obj.collection = stiBase.collection;\n }\n }\n\n logger.debug(\n `[manifest-generator] ✅ ${obj.className} now has ${Object.keys(mergedFields).length} fields (including inherited)`,\n );\n }\n\n // A model subclass inherits every generated surface (and `sensitive`) it\n // leaves unset from its parent model. Before the collection pass below,\n // so a subclass's collection inherits the subclass's effective surface.\n this.applySubclassExposureInheritance(manifest, objectsByName);\n\n // SECOND PASS: Handle collection classes that should inherit from their item class\n // This must happen AFTER STI field merging so item classes have their tableName set\n for (const obj of Object.values(manifest.objects)) {\n // Check if this is a collection class (extends SmrtCollection)\n const isCollection =\n obj.extends === 'SmrtCollection' ||\n this.extendsCollection(obj, objectsByName, manifest);\n // Junction and report collections inherit their model's exposure too,\n // but keep their own storage naming (that predates this pass).\n if (\n !isCollection &&\n !this.extendsAnyCollectionBase(obj, objectsByName, manifest)\n ) {\n continue;\n }\n\n // Find the item class from _itemClass static property\n const itemClass = this.findItemClass(obj, manifest, objectsByName);\n if (!itemClass || itemClass === obj) continue;\n\n logger.debug(\n `[manifest-generator] ${obj.className} is a collection class for ${itemClass.className}`,\n );\n\n if (isCollection) {\n // Inherit tableName from item class (which may have inherited it from STI base)\n if (itemClass.decoratorConfig?.tableName) {\n obj.decoratorConfig = obj.decoratorConfig || {};\n obj.decoratorConfig.tableName = itemClass.decoratorConfig.tableName;\n logger.debug(\n `[manifest-generator] ${obj.className} inherits tableName: '${itemClass.decoratorConfig.tableName}' from item class ${itemClass.className}`,\n );\n }\n\n // Routes may use an explicit namespace independently of item storage.\n // Match registry registration, where decorator collection wins.\n if (typeof obj.decoratorConfig?.collection === 'string') {\n obj.collection = obj.decoratorConfig.collection;\n } else if (itemClass.collection !== obj.collection) {\n logger.debug(\n `[manifest-generator] ${obj.className} inherits collection: '${itemClass.collection}' from item class ${itemClass.className} (was '${obj.collection}')`,\n );\n obj.collection = itemClass.collection;\n }\n }\n\n // A collection class is generated as a resource of its own, so a\n // surface it leaves unset inherits its model's exposure: `false`,\n // the CRUD verbs of an `include` list, an `exclude` list, and\n // read-only MCP over a `sensitive` model. Without this an object-form\n // model config left the collection open on every transport. From an\n // `include` list only CRUD verbs and names only the collection declares\n // carry over: a name the model declares is the model's own method, and\n // a same-named collection method is a different operation, so it stays\n // closed until the collection lists it. See `registry/collection-exposure.ts`.\n const inherited = inheritCollectionExposure(\n obj.decoratorConfig || {},\n itemClass.decoratorConfig || {},\n {\n collection: new Set(Object.keys(obj.methods || {})),\n item: new Set(Object.keys(itemClass.methods || {})),\n },\n );\n if (Object.keys(inherited).length > 0) {\n obj.decoratorConfig = { ...(obj.decoratorConfig || {}), ...inherited };\n logger.debug(\n `[manifest-generator] ${obj.className} inherits ${Object.keys(inherited).join(', ')} exposure from item class ${itemClass.className}`,\n );\n }\n }\n }\n\n /**\n * The model a model class directly extends, from this manifest or an\n * external SMRT dependency's, or `undefined` when its parent is a framework\n * base, a collection or unknown, or when the class is itself a collection.\n */\n private findParentModel(\n obj: SmartObjectDefinition,\n manifest: SmartObjectManifest,\n objectsByName: Map<string, SmartObjectDefinition>,\n ): SmartObjectDefinition | undefined {\n const parentName = obj.extendsQualified || obj.extends;\n if (!parentName) return undefined;\n const simpleParent = this.simpleClassName(parentName);\n if (\n FRAMEWORK_ABSTRACT_BASE_NAMES.has(simpleParent) ||\n FRAMEWORK_METHOD_BASE_NAMES.has(simpleParent) ||\n isSmrtCollectionExtendsName(parentName)\n ) {\n return undefined;\n }\n if (\n this.extendsCollection(obj, objectsByName, manifest) ||\n this.extendsAnyCollectionBase(obj, objectsByName, manifest)\n ) {\n return undefined;\n }\n let parent =\n (obj.extendsQualified\n ? (manifest.objects[obj.extendsQualified] as\n | SmartObjectDefinition\n | undefined)\n : undefined) ?? objectsByName.get(obj.extends ?? simpleParent);\n if (parent === obj) parent = undefined;\n if (!parent && manifest.smrtDependencies?.length) {\n parent = this.loadParentFromExternalPackage(\n parentName,\n manifest.smrtDependencies,\n objectsByName,\n );\n }\n if (!parent || parent === obj) return undefined;\n if (\n this.extendsCollection(parent, objectsByName, manifest) ||\n this.extendsAnyCollectionBase(parent, objectsByName, manifest)\n ) {\n return undefined;\n }\n return parent;\n }\n\n /**\n * A model's config with the surfaces it inherits from its ancestors\n * (`registry/subclass-exposure.ts`), computed without mutating `obj` or any\n * external manifest entry.\n */\n private subclassEffectiveConfig(\n obj: SmartObjectDefinition,\n manifest: SmartObjectManifest,\n objectsByName: Map<string, SmartObjectDefinition>,\n memo: Map<SmartObjectDefinition, SmartObjectConfig>,\n visiting: Set<SmartObjectDefinition> = new Set(),\n ): SmartObjectConfig {\n const cached = memo.get(obj);\n if (cached) return cached;\n const own = obj.decoratorConfig || {};\n if (visiting.has(obj)) return own;\n visiting.add(obj);\n let config = own;\n const parent = this.findParentModel(obj, manifest, objectsByName);\n if (parent) {\n const inherited = inheritSubclassExposure(\n own,\n this.subclassEffectiveConfig(\n parent,\n manifest,\n objectsByName,\n memo,\n visiting,\n ),\n );\n if (Object.keys(inherited).length > 0) config = { ...own, ...inherited };\n }\n visiting.delete(obj);\n memo.set(obj, config);\n return config;\n }\n\n /**\n * Give every model subclass in this manifest the generated surfaces and\n * `sensitive` flag it leaves unset from its parent model. Without this an\n * STI child such as `Person extends Profile` was generated with the open\n * default surface, publishing every write and method `Profile` closes.\n */\n private applySubclassExposureInheritance(\n manifest: SmartObjectManifest,\n objectsByName: Map<string, SmartObjectDefinition>,\n ): void {\n const memo = new Map<SmartObjectDefinition, SmartObjectConfig>();\n const updates: Array<[SmartObjectDefinition, SmartObjectConfig]> = [];\n for (const obj of Object.values(manifest.objects)) {\n const effective = this.subclassEffectiveConfig(\n obj,\n manifest,\n objectsByName,\n memo,\n );\n if (effective !== (obj.decoratorConfig || {})) {\n updates.push([obj, effective]);\n }\n }\n for (const [obj, effective] of updates) {\n obj.decoratorConfig = effective;\n logger.debug(\n `[manifest-generator] ${obj.className} inherits generated-surface exposure from ${obj.extends}`,\n );\n }\n }\n\n /**\n * Fail the build when a model subclass's own `@smrt()` opens a generated\n * operation (a CRUD verb or a parent method, on REST, MCP or CLI) that its\n * parent model closes, or drops its parent's `sensitive: true`, without\n * naming it in `widenParentExposure`. Runs after inheritance, so only a\n * subclass's own config can trip it.\n */\n private assertSubclassExposure(manifest: SmartObjectManifest): void {\n const objectsByName = new Map<string, SmartObjectDefinition>();\n for (const objectDef of Object.values(manifest.objects)) {\n objectsByName.set(objectDef.className, objectDef);\n }\n const memo = new Map<SmartObjectDefinition, SmartObjectConfig>();\n const findings: Parameters<typeof formatSubclassExposureEscalations>[0] =\n [];\n for (const obj of Object.values(manifest.objects)) {\n const parent = this.findParentModel(obj, manifest, objectsByName);\n if (!parent) continue;\n const childConfig = this.subclassEffectiveConfig(\n obj,\n manifest,\n objectsByName,\n memo,\n );\n const parentConfig = this.subclassEffectiveConfig(\n parent,\n manifest,\n objectsByName,\n memo,\n );\n const parentOperations = Object.entries(parent.methods || {})\n .filter(([, method]) => method.isPublic !== false)\n .map(([name]) => name);\n const escalations = findSubclassExposureEscalations(\n childConfig,\n parentConfig,\n parentOperations,\n );\n const stale = findStaleWidenings(childConfig, parentConfig);\n if (escalations.length > 0 || stale.length > 0) {\n findings.push({\n subclass: obj.qualifiedName || obj.className,\n parent: parent.qualifiedName || parent.className,\n escalations,\n stale,\n });\n }\n }\n if (findings.length > 0) {\n throw new ConfigurationError(\n formatSubclassExposureEscalations(findings),\n 'CONFIG_SUBCLASS_EXPOSURE',\n );\n }\n }\n\n /**\n * Fail the build when a collection class opens a generated CRUD write (MCP\n * or CLI) that its model keeps closed. Runs after inheritance, so only a\n * collection's own `@smrt()` surface can trip it.\n */\n private assertCollectionExposure(manifest: SmartObjectManifest): void {\n const objectsByName = new Map(\n Object.values(manifest.objects).map((objectDef) => [\n objectDef.className,\n objectDef,\n ]),\n );\n const findings: Parameters<typeof formatCollectionWriteEscalations>[0] = [];\n for (const obj of Object.values(manifest.objects)) {\n if (\n obj.extends !== 'SmrtCollection' &&\n !this.extendsCollection(obj, objectsByName, manifest) &&\n !this.extendsAnyCollectionBase(obj, objectsByName, manifest)\n ) {\n continue;\n }\n const itemClass = this.findItemClass(obj, manifest, objectsByName);\n if (!itemClass || itemClass === obj) continue;\n const escalations = findCollectionWriteEscalations(\n obj.decoratorConfig || {},\n itemClass.decoratorConfig || {},\n );\n if (escalations.length > 0) {\n findings.push({\n collection: obj.qualifiedName || obj.className,\n model: itemClass.qualifiedName || itemClass.className,\n escalations,\n });\n }\n }\n if (findings.length > 0) {\n throw new ConfigurationError(\n formatCollectionWriteEscalations(findings),\n 'CONFIG_COLLECTION_EXPOSURE',\n );\n }\n }\n\n /**\n * Whether a class descends from any SMRT collection base (`SmrtCollection`,\n * `SmrtJunction`, `SmrtJunctionBase`, `SmrtReportCollection`), following\n * parents declared in this manifest.\n */\n private extendsAnyCollectionBase(\n obj: SmartObjectDefinition,\n objectsByName: Map<string, SmartObjectDefinition>,\n manifest?: SmartObjectManifest,\n ): boolean {\n let current: SmartObjectDefinition | undefined = obj;\n const visited = new Set<SmartObjectDefinition>();\n while (current?.extends) {\n if (isSmrtCollectionExtendsName(current.extends)) return true;\n if (visited.has(current)) return false;\n visited.add(current);\n current = this.namedParent(current, objectsByName, manifest);\n }\n return false;\n }\n\n /**\n * Check if a class extends SmrtCollection (directly or indirectly)\n *\n * @param obj - The object definition to check\n * @param objectsByName - Map of className -> objectDef for lookups\n * @returns true if this class extends SmrtCollection\n */\n private extendsCollection(\n obj: SmartObjectDefinition,\n objectsByName: Map<string, SmartObjectDefinition>,\n manifest?: SmartObjectManifest,\n ): boolean {\n // Walk up inheritance chain looking for SmrtCollection\n let current: SmartObjectDefinition | undefined = obj;\n const visited = new Set<SmartObjectDefinition>();\n\n while (current?.extends) {\n if (visited.has(current)) break;\n visited.add(current);\n\n if (current.extends === 'SmrtCollection') return true;\n\n current = this.namedParent(current, objectsByName, manifest);\n }\n\n return false;\n }\n\n /**\n * Find the item class for a collection class\n *\n * Lookup priority:\n * 1. extendsTypeArg - Generic type argument from extends clause (e.g., \"Meeting\" from SmrtCollection<Meeting>)\n * 2. _itemClass static property - May be captured by AST scanner\n * 3. Name-based inference - Fallback (e.g., \"Meetings\" -> \"Meeting\")\n *\n * @param collectionObj - The collection class definition\n * @param manifest - The manifest\n * @param objectsByName - Map of className -> objectDef for lookups\n * @returns Item class definition or undefined\n */\n private findItemClass(\n collectionObj: SmartObjectDefinition,\n manifest: SmartObjectManifest,\n objectsByName: Map<string, SmartObjectDefinition>,\n ): SmartObjectDefinition | undefined {\n // PRIORITY 1: Use generic type argument from extends clause\n // This is the most reliable method: SmrtCollection<Meeting> -> \"Meeting\"\n if (collectionObj.extendsTypeArg) {\n const itemClassName = collectionObj.extendsTypeArg;\n logger.debug(\n `[manifest-generator] ${collectionObj.className} has extendsTypeArg: ${itemClassName}`,\n );\n\n // Try to find the item class by name in local manifest\n const itemClass = objectsByName.get(itemClassName);\n if (itemClass) {\n logger.debug(\n `[manifest-generator] Found item class ${itemClassName} in local manifest`,\n );\n return itemClass;\n }\n\n // Try loading from external packages\n if (manifest.smrtDependencies && manifest.smrtDependencies.length > 0) {\n const externalItemClass = this.loadParentFromExternalPackage(\n itemClassName,\n manifest.smrtDependencies,\n objectsByName,\n );\n if (externalItemClass) {\n logger.debug(\n `[manifest-generator] Found item class ${itemClassName} in external package`,\n );\n return externalItemClass;\n }\n }\n }\n\n // PRIORITY 2: Look for _itemClass static field in the collection class\n // This is defined like: static readonly _itemClass = Meeting;\n // Note: AST scanner currently skips static properties, so this rarely works\n const itemClassField = collectionObj.fields._itemClass;\n\n if (itemClassField) {\n // Extract class name from the field's default value or metadata\n // The AST scanner might capture this as a reference\n const itemClassName = itemClassField.related || itemClassField.default;\n\n if (itemClassName && typeof itemClassName === 'string') {\n // Try to find the item class by name\n const itemClass = objectsByName.get(itemClassName);\n if (itemClass) {\n return itemClass;\n }\n\n // Try loading from external packages\n if (manifest.smrtDependencies && manifest.smrtDependencies.length > 0) {\n return this.loadParentFromExternalPackage(\n itemClassName,\n manifest.smrtDependencies,\n objectsByName,\n );\n }\n }\n }\n\n // PRIORITY 3: Fallback - Try to infer from collection class name\n // Generate candidate item class names and check if they exist\n const collectionName = collectionObj.className;\n const candidates: string[] = [];\n\n // Strip \"Collection\" suffix first if present\n let baseName = collectionName;\n if (baseName.endsWith('Collection')) {\n baseName = baseName.slice(0, -'Collection'.length);\n }\n\n // Generate singularization candidates (order matters - try most specific first)\n // 1. Exact name (e.g., \"Event\" from \"EventCollection\")\n candidates.push(baseName);\n\n // 2. Remove trailing 's' (e.g., \"Meetings\" -> \"Meeting\")\n if (baseName.endsWith('s') && baseName.length > 1) {\n candidates.push(baseName.slice(0, -1));\n }\n\n // 3. Handle 'ies' -> 'y' (e.g., \"Categories\" -> \"Category\")\n if (baseName.endsWith('ies') && baseName.length > 3) {\n candidates.push(`${baseName.slice(0, -3)}y`);\n }\n\n // 4. Handle 'es' -> '' for words ending in s/x/z/ch/sh (e.g., \"Statuses\" -> \"Status\")\n if (baseName.endsWith('es') && baseName.length > 2) {\n candidates.push(baseName.slice(0, -2));\n }\n\n // Try each candidate against local classes first, then external packages\n // Skip candidates that match the collection class itself\n for (const candidate of candidates) {\n if (candidate === collectionObj.className) continue; // Don't match self\n const itemClass = objectsByName.get(candidate);\n if (itemClass) {\n return itemClass;\n }\n }\n\n // Try loading from external packages\n if (manifest.smrtDependencies && manifest.smrtDependencies.length > 0) {\n for (const candidate of candidates) {\n if (candidate === collectionObj.className) continue; // Don't match self\n const itemClass = this.loadParentFromExternalPackage(\n candidate,\n manifest.smrtDependencies,\n objectsByName,\n );\n if (itemClass) {\n return itemClass;\n }\n }\n }\n\n return undefined;\n }\n\n /**\n * Check if a class uses STI (either explicitly or inherited from an ancestor)\n *\n * Walks up the inheritance chain to find if any ancestor has tableStrategy: 'sti'.\n * If found, all descendants inherit STI and should have fields merged.\n * Also checks external SMRT packages for parent class definitions.\n *\n * @param obj - The object definition to check\n * @param objectsByName - Map of className -> objectDef for lookups\n * @param manifest - The manifest (for accessing smrtDependencies)\n * @returns true if this class uses STI (directly or inherited)\n */\n private isSTIClass(\n obj: SmartObjectDefinition,\n objectsByName: Map<string, SmartObjectDefinition>,\n manifest: SmartObjectManifest,\n ): boolean {\n // Check if explicitly marked as STI\n if (obj.decoratorConfig?.tableStrategy === 'sti') {\n return true;\n }\n\n // Walk up the inheritance chain looking for STI base\n let currentClass: string | undefined = this.parentRef(obj);\n const visited = new Set<string>();\n\n while (currentClass) {\n if (visited.has(currentClass)) {\n break; // Circular inheritance, stop\n }\n visited.add(currentClass);\n\n // Skips self-reference (local class with same name as imported parent).\n const parentDef = this.resolveParentDefinition(\n currentClass,\n obj,\n manifest,\n objectsByName,\n );\n\n if (!parentDef) break; // Parent not found anywhere\n\n // Check if this ancestor uses STI\n if (parentDef.decoratorConfig?.tableStrategy === 'sti') {\n return true; // Found STI ancestor\n }\n\n currentClass = this.parentRef(parentDef);\n }\n\n return false; // No STI in hierarchy\n }\n\n /**\n * Find the STI base class for a given object\n *\n * Walks up the inheritance chain to find the first ancestor that defines\n * tableStrategy: 'sti'. This is the class that owns the shared table.\n *\n * @param obj - The object definition to find the STI base for\n * @param objectsByName - Map of className -> objectDef for lookups\n * @param manifest - The manifest (for accessing smrtDependencies)\n * @returns The STI base class definition, or the object itself if it's the base\n */\n private findSTIBase(\n obj: SmartObjectDefinition,\n objectsByName: Map<string, SmartObjectDefinition>,\n manifest: SmartObjectManifest,\n ): SmartObjectDefinition | undefined {\n // Track the oldest STI class found as we walk up\n let stiBase: SmartObjectDefinition | undefined;\n\n // If this object explicitly defines STI, it's a candidate (but ancestors may also be STI)\n if (obj.decoratorConfig?.tableStrategy === 'sti') {\n stiBase = obj;\n }\n\n // Walk up the inheritance chain looking for the oldest STI base\n let currentClass: string | undefined = this.parentRef(obj);\n const visited = new Set<string>();\n\n while (currentClass) {\n if (visited.has(currentClass)) {\n break; // Circular inheritance, stop\n }\n visited.add(currentClass);\n\n // Skips self-reference (local class with same name as imported parent).\n const parentDef = this.resolveParentDefinition(\n currentClass,\n obj,\n manifest,\n objectsByName,\n );\n\n if (!parentDef) break; // Parent not found anywhere\n\n // Check if this ancestor defines STI - if so, it becomes the new candidate base\n // (we keep walking to find the oldest/root STI class)\n if (parentDef.decoratorConfig?.tableStrategy === 'sti') {\n stiBase = parentDef;\n }\n\n currentClass = this.parentRef(parentDef);\n }\n\n return stiBase; // Return the oldest STI ancestor found (or undefined if none)\n }\n\n /**\n * Load parent class definition from external SMRT packages\n *\n * When a child class extends a parent from an external package (e.g., praeco's Council extends\n * smrt-profiles' Organization), this method loads the parent's manifest and extracts the\n * parent's field definitions.\n *\n * @param parentClassName - Name of the parent class to find\n * @param smrtDependencies - List of external SMRT packages to search\n * @param objectsByName - Map to cache loaded external objects\n * @returns Parent object definition if found, undefined otherwise\n */\n private loadParentFromExternalPackage(\n parentClassName: string,\n smrtDependencies: string[],\n objectsByName: Map<string, SmartObjectDefinition>,\n ): SmartObjectDefinition | undefined {\n // Try each external SMRT dependency\n for (const packageName of smrtDependencies) {\n const externalManifest = loadExternalManifestSync(packageName);\n\n if (!externalManifest) {\n continue;\n }\n\n // Use lookupInManifest for O(1) lookup via cached className index\n // Handles both qualified names and simple class names\n const parentObj = lookupInManifest(externalManifest, parentClassName);\n\n if (parentObj) {\n // Cache the loaded parent object for future lookups, but never over\n // a local class of the same simple name: that entry is this\n // package's own parent for its other subclasses (#4145).\n if (!objectsByName.has(parentObj.className)) {\n objectsByName.set(parentObj.className, parentObj);\n }\n if (!objectsByName.has(parentObj.className.toLowerCase())) {\n objectsByName.set(parentObj.className.toLowerCase(), parentObj);\n }\n\n return parentObj;\n }\n }\n\n return undefined;\n }\n\n /**\n * Determine import path from package.json exports\n *\n * Tries the following strategies in order:\n * 1. package.json exports[\"./objects\"] - Specific objects export\n * 2. package.json exports[\".\"] - Main export\n * 3. package.json main - Main field\n * 4. Fallback to package name\n */\n /**\n * Determine the specifier consumers should import an object from.\n *\n * `filePath` was accepted (and ignored — the parameter was named\n * `_filePath`) since before this fix, so every object always resolved to\n * the bare package name regardless of where it actually lived. That is\n * wrong for an object scanned from a file only a non-root `exports`\n * subpath serves (e.g. `./server`): the manifest advertised the object as\n * importable from the package root, but the root bundle never exports it,\n * so a consumer dynamically importing by manifest metadata (or generating\n * `.smrt/register.js`, `consumer-plugin/index.ts`'s own\n * `determineImportPath`) silently failed to find it. That is smrt#2845 —\n * `DataSurfaceActionIdempotencyState` in `@happyvertical/smrt-agents` lives\n * under `src/server/` (served only by the `./server` export), but the\n * manifest pointed consumers at the bare `@happyvertical/smrt-agents`\n * specifier.\n *\n * Strategy: match `filePath` against the package's `exports` subpaths —\n * `src/<segment>/...` or `src/<segment>.ts` maps to the `./<segment>`\n * export key — and prefer the longest matching segment. Falls back to the\n * legacy behavior (bare package name, with the `./objects` special case)\n * when the file does not match any subpath, which covers objects reachable\n * from the root `.` entry point.\n */\n private determineImportPath(\n packageJson: PackageJsonLike,\n filePath?: string,\n ): string {\n // Only invoked once a package name is known (guarded at the call site),\n // so `name` is always present here.\n const packageName = packageJson.name as string;\n\n if (packageJson.exports && typeof packageJson.exports === 'object') {\n const subpathSegment = this.matchExportsSubpath(\n packageJson.exports,\n filePath,\n );\n if (subpathSegment) {\n return `${packageName}/${subpathSegment}`;\n }\n\n // Legacy special case, kept for packages whose `./objects` export\n // predates file-path-based matching and whose objects' `filePath`\n // does not follow the `src/objects/...` convention above.\n if (packageJson.exports['./objects']) {\n return `${packageName}/objects`;\n }\n }\n\n // Strategy 2/3: main field or bare fallback — both resolve to the\n // package root, which is where an unmatched object is assumed to live.\n return packageName;\n }\n\n /**\n * Match a scanned object's `filePath` against a package's `exports` map,\n * returning the longest matching non-root subpath segment (e.g. `\"server\"`\n * for `./server`), or `undefined` when the file does not correspond to any\n * declared subpath (the object is assumed reachable from the root `.`\n * entry point instead).\n */\n private matchExportsSubpath(\n exportsMap: Record<string, unknown>,\n filePath?: string,\n ): string | undefined {\n if (!filePath) return undefined;\n\n const normalized = filePath.replace(/\\\\/g, '/');\n const srcMarker = 'src/';\n const srcIndex = normalized.lastIndexOf(srcMarker);\n if (srcIndex === -1) return undefined;\n const relativeToSrc = normalized.slice(srcIndex + srcMarker.length);\n\n // Path components with any source-file extension stripped from the last\n // one, so `lib/models/Category.ts` and `server.js` both compare as plain\n // component lists (`['lib','models','Category']`, `['server']`).\n const pathParts = relativeToSrc.split('/');\n const lastIndex = pathParts.length - 1;\n pathParts[lastIndex] = pathParts[lastIndex].replace(\n /\\.(ts|tsx|js|jsx|mjs|cjs)$/,\n '',\n );\n\n const segments = Object.keys(exportsMap)\n .filter(\n (key) =>\n key !== '.' &&\n key !== './package.json' &&\n !key.includes('*') &&\n // Exclude subpaths that resolve to a non-JS asset (e.g. the\n // `./manifest`/`./manifest.json` convention pointing at\n // `dist/manifest.json`). No @smrt object's source file can ever\n // legitimately resolve there, so this only guards against a\n // coincidental `src/manifest/...` path being misattributed to it.\n !targetsJsonAsset(exportsMap[key]),\n )\n .map((key) => key.replace(/^\\.\\//, ''))\n .filter((segment) => segment.length > 0)\n // Longest first so a nested segment (rare) wins over a shorter prefix.\n .sort((a, b) => b.length - a.length);\n\n return segments.find((segment) => {\n const segmentParts = segment.split('/');\n // Match the segment's components as a contiguous run anywhere in the\n // file's path — not just a root-level prefix. Handles both a direct\n // subpath directory (`server/x.ts` for `./server`) and a re-export\n // barrel whose real source lives deeper than its export key implies\n // (`@happyvertical/smrt-products`: `./models` -> `src/models.ts` ->\n // `export * from './lib/models/index'`, with the actual `@smrt()`\n // classes scanned from `src/lib/models/*.ts` — `relativeToSrc` is\n // `lib/models/Category.ts`, which contains `models` as a component,\n // just not at index 0).\n for (\n let start = 0;\n start <= pathParts.length - segmentParts.length;\n start++\n ) {\n if (\n segmentParts.every(\n (part, offset) => pathParts[start + offset] === part,\n )\n ) {\n return true;\n }\n }\n return false;\n });\n }\n\n /**\n * Generate TypeScript interfaces from manifest\n */\n generateTypeDefinitions(manifest: SmartObjectManifest): string {\n const interfaces: string[] = [];\n\n // Manifest key order follows scan/discovery order, which is not stable\n // across runs (#2749): the vite-plugin's server-mode `@smrt/types`\n // resolution calls this method directly, so sort deterministically\n // before emitting for the same reason as the prebuild/client-mode paths.\n const sortedEntries = Object.entries(manifest.objects).sort(\n ([leftKey, left], [rightKey, right]) =>\n compareText(\n left.qualifiedName || leftKey,\n right.qualifiedName || rightKey,\n ) || compareText(leftKey, rightKey),\n );\n for (const [_name, obj] of sortedEntries) {\n interfaces.push(this.generateInterface(obj));\n }\n\n return interfaces.join('\\n\\n');\n }\n\n /**\n * Generate a single interface definition\n */\n private generateInterface(obj: SmartObjectDefinition): string {\n const fields = Object.entries(obj.fields)\n .map(([name, field]) => {\n const optional = !field.required ? '?' : '';\n const type = this.mapFieldTypeToTS(field.type);\n return ` ${name}${optional}: ${type};`;\n })\n .join('\\n');\n\n return `export interface ${obj.className}Data {\n${fields}\n}`;\n }\n\n /**\n * Map field types to TypeScript types\n */\n private mapFieldTypeToTS(fieldType: string): string {\n switch (fieldType) {\n case 'text':\n return 'string';\n case 'decimal':\n return 'number';\n case 'integer':\n return 'number';\n case 'boolean':\n return 'boolean';\n case 'datetime':\n return 'Date | string';\n case 'json':\n return 'any';\n case 'foreignKey':\n return 'string';\n case 'crossPackageRef':\n return 'string';\n default:\n return 'any';\n }\n }\n\n /**\n * Generate simple endpoint list for testing/documentation\n */\n generateRestEndpoints(manifest: SmartObjectManifest): string {\n const endpoints: string[] = [];\n\n for (const [_name, obj] of Object.entries(manifest.objects)) {\n const apiConfig = obj.decoratorConfig.api;\n if (apiConfig !== false) {\n endpoints.push(...this.getSimpleEndpoints(obj, manifest));\n }\n }\n\n return endpoints.join('\\n');\n }\n\n /**\n * Generate REST endpoint code implementations\n */\n generateRestEndpointCode(manifest: SmartObjectManifest): string {\n const endpoints: string[] = [];\n\n for (const [_name, obj] of Object.entries(manifest.objects)) {\n const apiConfig = obj.decoratorConfig.api;\n if (apiConfig !== false) {\n endpoints.push(this.generateRestEndpoint(obj));\n }\n }\n\n return endpoints.join('\\n\\n');\n }\n\n /**\n * Get simple endpoint strings for an object\n */\n private getApiRouteMetadata(\n obj: SmartObjectDefinition,\n actionName: string,\n actionDef: MethodDefinition | { isStatic?: boolean },\n ): {\n scope: 'item' | 'collection';\n method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n path: string;\n } {\n const config =\n obj.decoratorConfig.api && typeof obj.decoratorConfig.api === 'object'\n ? obj.decoratorConfig.api\n : undefined;\n // `@method({ httpMethod, path })` wins field by field over the class-level\n // `api.routes[action]` entry, the same merge `resolveApiActionRouteConfig`\n // and the knowledge artifact perform. Reading `routes` alone printed the\n // PRE-migration verb and path for a class that had moved to the decorator\n // (#2686).\n const effective = resolveEffectiveActionMetadata({\n actionName,\n method: actionDef,\n apiConfig: config,\n });\n const normalizedPath = (effective.path || actionName)\n .split('/')\n .map((segment) => segment.trim())\n .filter(Boolean)\n .join('/');\n const isCollectionClass =\n obj.extends === 'SmrtCollection' || !!obj.extendsTypeArg;\n\n const defaultScope =\n isCollectionClass || actionDef.isStatic ? 'collection' : 'item';\n\n return {\n scope: resolveCustomActionMetadata({\n actionName,\n method: actionDef,\n apiConfig: config,\n defaultScope,\n }).scope,\n method: effective.httpMethod ?? 'POST',\n path: normalizedPath || actionName,\n };\n }\n\n private getSimpleEndpoints(\n obj: SmartObjectDefinition,\n manifest?: SmartObjectManifest,\n ): string[] {\n const { collection } = obj;\n const config = obj.decoratorConfig.api;\n const exclude = (typeof config === 'object' && config?.exclude) || [];\n const include =\n (typeof config === 'object' && config?.include) || undefined;\n const isCollectionClass =\n obj.extends === 'SmrtCollection' || !!obj.extendsTypeArg;\n const isModelClassName = createManifestClassNamePredicate(manifest);\n\n const endpoints: string[] = [];\n\n // Determine which operations to include\n const shouldInclude = (op: string) => {\n if (include && !include.includes(op)) return false;\n if (exclude.includes(op)) return false;\n return true;\n };\n\n if (!isCollectionClass) {\n if (shouldInclude('list')) {\n endpoints.push(`GET /${collection}`);\n }\n if (shouldInclude('create')) {\n endpoints.push(`POST /${collection}`);\n }\n if (shouldInclude('get')) {\n endpoints.push(`GET /${collection}/:id`);\n }\n if (shouldInclude('update')) {\n endpoints.push(`PUT /${collection}/:id`);\n }\n if (shouldInclude('delete')) {\n endpoints.push(`DELETE /${collection}/:id`);\n }\n }\n\n // Custom actions read the ONE shared exposure resolver rather than a local\n // copy of the include/exclude rule. This listing is a published virtual\n // module (`@happyvertical/smrt-virt-routes`), so a stale rule here\n // advertises operations whose routes the emitters never wrote -- exactly\n // the consumer disagreement #2686 exists to close.\n for (const [actionName, actionDef] of Object.entries(obj.methods)) {\n if (\n !resolveApiMethodExposure({\n actionName,\n method: actionDef,\n apiConfig: config,\n isCollectionClass,\n ...(isModelClassName ? { isModelClassName } : {}),\n }).exposed\n ) {\n continue;\n }\n\n const route = this.getApiRouteMetadata(obj, actionName, actionDef);\n const suffix = route.scope === 'collection' ? '' : '/:id';\n endpoints.push(`${route.method} /${collection}${suffix}/${route.path}`);\n }\n\n return endpoints;\n }\n\n /**\n * Generate a single REST endpoint\n */\n private generateRestEndpoint(obj: SmartObjectDefinition): string {\n const { collection, className } = obj;\n const config = obj.decoratorConfig.api;\n const exclude = (typeof config === 'object' && config?.exclude) || [];\n const include =\n (typeof config === 'object' && config?.include) || undefined;\n\n const operations: string[] = [];\n\n // Determine which operations to include\n const shouldInclude = (op: string) => {\n if (include && !include.includes(op)) return false;\n if (exclude.includes(op)) return false;\n return true;\n };\n\n if (shouldInclude('list')) {\n operations.push(` // GET /${collection} - List ${collection}`);\n operations.push(` app.get('/${collection}', async (req: Request) => {`);\n operations.push(\n ` const collection = await get${className}Collection();`,\n );\n operations.push(' const items = await collection.list(req.query);');\n operations.push(' return Response.json(items);');\n operations.push(' });');\n }\n\n if (shouldInclude('get')) {\n operations.push(` // GET /${collection}/:id - Get ${className}`);\n operations.push(\n ` app.get('/${collection}/:id', async (req: Request) => {`,\n );\n operations.push(\n ` const collection = await get${className}Collection();`,\n );\n operations.push(' const item = await collection.get(req.params.id);');\n operations.push(\n ` if (!item) return new Response('Not found', { status: 404 });`,\n );\n operations.push(' return Response.json(item);');\n operations.push(' });');\n }\n\n if (shouldInclude('create')) {\n operations.push(` // POST /${collection} - Create ${className}`);\n operations.push(` app.post('/${collection}', async (req: Request) => {`);\n operations.push(\n ` const collection = await get${className}Collection();`,\n );\n operations.push(' const data = await req.json();');\n operations.push(' const item = await collection.create(data);');\n operations.push(' return Response.json(item, { status: 201 });');\n operations.push(' });');\n }\n\n if (shouldInclude('update')) {\n operations.push(` // PUT /${collection}/:id - Update ${className}`);\n operations.push(\n ` app.put('/${collection}/:id', async (req: Request) => {`,\n );\n operations.push(\n ` const collection = await get${className}Collection();`,\n );\n operations.push(' const data = await req.json();');\n operations.push(\n ' const item = await collection.update(req.params.id, data);',\n );\n operations.push(\n ` if (!item) return new Response('Not found', { status: 404 });`,\n );\n operations.push(' return Response.json(item);');\n operations.push(' });');\n }\n\n if (shouldInclude('delete')) {\n operations.push(` // DELETE /${collection}/:id - Delete ${className}`);\n operations.push(\n ` app.delete('/${collection}/:id', async (req: Request) => {`,\n );\n operations.push(\n ` const collection = await get${className}Collection();`,\n );\n operations.push(\n ' const success = await collection.delete(req.params.id);',\n );\n operations.push(\n ` if (!success) return new Response('Not found', { status: 404 });`,\n );\n operations.push(` return new Response('', { status: 204 });`);\n operations.push(' });');\n }\n\n return `// ${className} endpoints\\n${operations.join('\\n')}`;\n }\n\n /**\n * Generate simple MCP tool names for testing/documentation\n */\n generateMCPTools(manifest: SmartObjectManifest): string {\n const tools: string[] = [];\n\n for (const obj of this.selectMCPToolOwners(manifest)) {\n tools.push(...this.getSimpleMCPToolNames(obj));\n }\n\n return tools.join('\\n');\n }\n\n /**\n * Choose exactly one canonical MCP owner per `collection`.\n *\n * MCP tool names are keyed on `collection`, but the framework's normal shape\n * puts a model class and its `FooCollection` access class in the manifest\n * under the SAME collection. Emitting both produces duplicate tool names with\n * differing create/update schemas, and an MCP client that indexes tools by\n * name then resolves an arbitrary one (#2631 review).\n *\n * Owners are ranked, in order:\n *\n * 1. The model class beats the collection-access class. `create`/`update`\n * input schemas derive from `obj.fields`, and the row shape lives on the\n * model, not on the access class.\n * 2. The shallowest class in the collection's own inheritance tree wins. An\n * STI family shares one `collection`, and the base defines the shared row\n * contract; a leaf subclass would narrow the emitted schema to one variant\n * of a table the tool addresses as a whole.\n * 3. Remaining ties break lexically on the qualified name, so the emitted\n * surface is deterministic across generation passes.\n */\n private selectMCPToolOwners(\n manifest: SmartObjectManifest,\n ): SmartObjectDefinition[] {\n const candidatesByCollection = new Map<string, SmartObjectDefinition[]>();\n\n for (const obj of Object.values(manifest.objects)) {\n if (obj.decoratorConfig.mcp === false) continue;\n const bucket = candidatesByCollection.get(obj.collection);\n if (bucket) bucket.push(obj);\n else candidatesByCollection.set(obj.collection, [obj]);\n }\n\n return [...candidatesByCollection.entries()]\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n .map(([, candidates]) => {\n const depths = this.inheritanceDepthsWithin(candidates);\n let owner = candidates[0];\n for (const candidate of candidates.slice(1)) {\n if (this.preferMCPToolOwner(candidate, owner, depths)) {\n owner = candidate;\n }\n }\n return owner;\n });\n }\n\n /** Stable identity for an MCP owner candidate. */\n private mcpOwnerKey(obj: SmartObjectDefinition): string {\n return obj.qualifiedName || obj.className;\n }\n\n /**\n * Depth of each candidate inside the candidate set's OWN inheritance tree,\n * keyed by {@link mcpOwnerKey}. A candidate with no candidate ancestor is a\n * root at depth 0. Ancestors outside the set (framework bases, classes in\n * other collections) do not add depth: only the shared-collection family\n * decides which member is canonical.\n *\n * Parents resolve on `extendsQualified` first. Two packages may legally\n * contribute same-simple-name classes to one collection, so a simple-name\n * match is used only when it is unambiguous within the candidate set —\n * otherwise the walk stops rather than linking unrelated classes.\n */\n private inheritanceDepthsWithin(\n candidates: SmartObjectDefinition[],\n ): Map<string, number> {\n const byQualified = new Map<string, SmartObjectDefinition>();\n const bySimpleName = new Map<string, SmartObjectDefinition | null>();\n for (const candidate of candidates) {\n byQualified.set(this.mcpOwnerKey(candidate), candidate);\n const simple = this.simpleClassName(candidate.className);\n // `null` marks an ambiguous simple name; never resolve through it.\n bySimpleName.set(simple, bySimpleName.has(simple) ? null : candidate);\n }\n\n const resolveParent = (\n obj: SmartObjectDefinition,\n ): SmartObjectDefinition | undefined => {\n if (obj.extendsQualified) return byQualified.get(obj.extendsQualified);\n if (!obj.extends) return undefined;\n return bySimpleName.get(this.simpleClassName(obj.extends)) ?? undefined;\n };\n\n const depths = new Map<string, number>();\n for (const candidate of candidates) {\n const key = this.mcpOwnerKey(candidate);\n let depth = 0;\n let current: SmartObjectDefinition | undefined = candidate;\n const visited = new Set<string>([key]);\n while (current) {\n const parent: SmartObjectDefinition | undefined =\n resolveParent(current);\n if (!parent) break;\n const parentKey = this.mcpOwnerKey(parent);\n // Circular or self-referential extends: stop rather than loop.\n if (visited.has(parentKey)) break;\n visited.add(parentKey);\n depth += 1;\n current = parent;\n }\n depths.set(key, depth);\n }\n return depths;\n }\n\n /** True when `candidate` is the better canonical MCP owner than `current`. */\n private preferMCPToolOwner(\n candidate: SmartObjectDefinition,\n current: SmartObjectDefinition,\n depths: Map<string, number>,\n ): boolean {\n const candidateIsCollection = this.isCollectionAccessClass(candidate);\n const currentIsCollection = this.isCollectionAccessClass(current);\n if (candidateIsCollection !== currentIsCollection) {\n return !candidateIsCollection;\n }\n\n const candidateKey = this.mcpOwnerKey(candidate);\n const currentKey = this.mcpOwnerKey(current);\n\n const candidateDepth = depths.get(candidateKey) ?? 0;\n const currentDepth = depths.get(currentKey) ?? 0;\n if (candidateDepth !== currentDepth) {\n return candidateDepth < currentDepth;\n }\n\n return candidateKey < currentKey;\n }\n\n /**\n * Collection-access class detection, matching the convention already used by\n * `generateRestRoutes` (direct base / generic type argument) plus the\n * `FooCollection` naming fallback this generator uses elsewhere, so a deeper\n * subclass that carries no type argument of its own is still recognised.\n */\n private isCollectionAccessClass(obj: SmartObjectDefinition): boolean {\n return (\n obj.extends === 'SmrtCollection' ||\n !!obj.extendsTypeArg ||\n obj.className.endsWith('Collection')\n );\n }\n\n /**\n * Generate MCP tool JSON definitions\n */\n generateMCPToolsCode(manifest: SmartObjectManifest): string {\n const tools: string[] = [];\n\n for (const obj of this.selectMCPToolOwners(manifest)) {\n const code = this.generateMCPTool(obj);\n // An object whose every operation is excluded contributes nothing;\n // pushing '' would emit a hole in the array literal (#2631).\n if (code) tools.push(code);\n }\n\n return tools.length > 0 ? `[\\n${tools.join(',\\n')}\\n]` : '[]';\n }\n\n /**\n * Get simple MCP tool names for an object\n */\n private getSimpleMCPToolNames(obj: SmartObjectDefinition): string[] {\n const { collection } = obj;\n const config = obj.decoratorConfig.mcp;\n const exclude = (typeof config === 'object' && config?.exclude) || [];\n const include =\n (typeof config === 'object' && config?.include) || undefined;\n\n const tools: string[] = [];\n\n const shouldInclude = (op: string) => {\n if (include && !include.includes(op)) return false;\n if (exclude.includes(op)) return false;\n return true;\n };\n\n if (shouldInclude('list')) {\n tools.push(`list_${collection}`);\n }\n if (shouldInclude('get')) {\n tools.push(`get_${collection}`);\n }\n if (shouldInclude('create')) {\n tools.push(`create_${collection}`);\n }\n if (shouldInclude('update')) {\n tools.push(`update_${collection}`);\n }\n if (shouldInclude('delete')) {\n tools.push(`delete_${collection}`);\n }\n\n return tools;\n }\n\n /**\n * Generate a single MCP tool\n */\n private generateMCPTool(obj: SmartObjectDefinition): string {\n const { collection } = obj;\n const config = obj.decoratorConfig.mcp;\n const exclude = (typeof config === 'object' && config?.exclude) || [];\n const include =\n (typeof config === 'object' && config?.include) || undefined;\n\n const tools: string[] = [];\n\n const shouldInclude = (op: string) => {\n if (include && !include.includes(op)) return false;\n if (exclude.includes(op)) return false;\n return true;\n };\n\n if (shouldInclude('list')) {\n tools.push(` {\n name: \"list_${collection}\",\n description: \"List ${collection}\",\n inputSchema: {\n type: \"object\",\n properties: {\n limit: { type: \"number\" },\n offset: { type: \"number\" },\n where: { type: \"object\" }\n }\n }\n }`);\n }\n\n if (shouldInclude('get')) {\n tools.push(` {\n name: \"get_${collection}\",\n description: \"Get a ${collection} entry by ID\",\n inputSchema: {\n type: \"object\",\n properties: {\n id: { type: \"string\", description: \"The ${collection} entry ID\" }\n },\n required: [\"id\"]\n }\n }`);\n }\n\n const schemaProperties = JSON.stringify(\n this.generateSchemaProperties(obj.fields),\n null,\n 6,\n );\n\n if (shouldInclude('create')) {\n const requiredFields = Object.entries(obj.fields)\n .filter(([_, field]) => field.required)\n .map(([fieldName]) => fieldName);\n\n tools.push(` {\n name: \"create_${collection}\",\n description: \"Create a new ${collection} entry\",\n inputSchema: {\n type: \"object\",\n properties: ${schemaProperties},\n required: ${JSON.stringify(requiredFields)}\n }\n }`);\n }\n\n if (shouldInclude('update')) {\n tools.push(` {\n name: \"update_${collection}\",\n description: \"Update an existing ${collection} entry\",\n inputSchema: {\n type: \"object\",\n properties: {\n id: { type: \"string\", description: \"The ${collection} entry ID\" },\n data: {\n type: \"object\",\n description: \"Fields to update on the ${collection} entry\",\n properties: ${schemaProperties}\n }\n },\n required: [\"id\", \"data\"]\n }\n }`);\n }\n\n if (shouldInclude('delete')) {\n tools.push(` {\n name: \"delete_${collection}\",\n description: \"Delete a ${collection} entry by ID\",\n inputSchema: {\n type: \"object\",\n properties: {\n id: { type: \"string\", description: \"The ${collection} entry ID\" }\n },\n required: [\"id\"]\n }\n }`);\n }\n\n return tools.join(',\\n');\n }\n\n /**\n * Generate JSON schema properties for fields\n */\n private generateSchemaProperties(\n fields: Record<string, FieldDefinition>,\n ): Record<string, JsonSchemaProperty> {\n const properties: Record<string, JsonSchemaProperty> = {};\n\n for (const [name, field] of Object.entries(fields)) {\n properties[name] = {\n type: this.mapFieldTypeToJSON(field.type),\n description: field.description || `The ${name} field`,\n };\n\n if (field.min !== undefined) properties[name].minimum = field.min;\n if (field.max !== undefined) properties[name].maximum = field.max;\n if (field.minLength !== undefined)\n properties[name].minLength = field.minLength;\n if (field.maxLength !== undefined)\n properties[name].maxLength = field.maxLength;\n if (\n field.enum &&\n field.enum.length > 0 &&\n (field.type === 'text' ||\n field.type === 'integer' ||\n field.type === 'decimal')\n ) {\n properties[name].enum = [...field.enum];\n }\n }\n\n return properties;\n }\n\n /**\n * Map field types to JSON Schema types\n */\n private mapFieldTypeToJSON(fieldType: string): string {\n switch (fieldType) {\n case 'text':\n return 'string';\n case 'decimal':\n return 'number';\n case 'integer':\n return 'integer';\n case 'boolean':\n return 'boolean';\n case 'datetime':\n return 'string';\n case 'json':\n return 'object';\n case 'foreignKey':\n return 'string';\n case 'crossPackageRef':\n return 'string';\n default:\n return 'string';\n }\n }\n\n /**\n * Generate agent manifests for Agent subclasses (fifth pass).\n *\n * For any SmartObjectDefinition with `agent` in its decoratorConfig,\n * auto-generates:\n * - Permissions from uiSlots (manage:*) and CLI/MCP methods (execute:*)\n * - Features from uiSlots and exposed methods\n * - Menu items from uiSlots\n * - Component declarations from package.json exports\n *\n * @param manifest - The manifest to process in-place\n * @param packageName - Package name for component export paths\n * @param packageJson - Full package.json for component discovery\n */\n generateAgentManifests(\n manifest: SmartObjectManifest,\n packageName?: string,\n packageJson?: PackageJsonLike,\n ): void {\n for (const obj of Object.values(manifest.objects)) {\n if (!obj.decoratorConfig.agent) continue;\n\n const agentConfig = obj.decoratorConfig.agent;\n const slug = obj.className.toLowerCase();\n // staticProperties is an untyped AST capture; assert the shape the\n // scanner records for `static uiSlots` on Agent subclasses.\n const uiSlots: Record<string, AgentUISlotManifest> =\n (obj.staticProperties?.uiSlots as\n | Record<string, AgentUISlotManifest>\n | undefined) ?? {};\n\n // Derive permissions\n const permissions: AgentPermission[] = [];\n\n // From uiSlots: manage:<slotId>\n for (const [slotId, slot] of Object.entries(uiSlots)) {\n permissions.push({\n id: `manage:${slotId}`,\n label: `Manage ${(slot as AgentUISlotManifest).label || slotId}`,\n category: 'slot',\n defaultGranted: true,\n });\n }\n\n // From CLI/MCP methods: execute:<methodName>\n const exposedMethods = this.getExposedMethods(obj);\n for (const methodName of exposedMethods) {\n permissions.push({\n id: `execute:${methodName}`,\n label: `Execute ${methodName}`,\n category: 'method',\n defaultGranted: true,\n });\n }\n\n // Derive features\n const features: AgentFeature[] = [];\n\n for (const [slotId, slot] of Object.entries(uiSlots)) {\n const typedSlot = slot as AgentUISlotManifest;\n features.push({\n id: slotId,\n label: typedSlot.label || slotId,\n description: typedSlot.description,\n type: 'slot',\n });\n }\n\n for (const methodName of exposedMethods) {\n features.push({\n id: methodName,\n label: methodName,\n type: 'method',\n });\n }\n\n // Derive menu items from uiSlots (sorted by order)\n const menuItems: AgentMenuItem[] = Object.entries(uiSlots)\n .map(([slotId, slot]) => {\n const typedSlot = slot as AgentUISlotManifest;\n return {\n id: slotId,\n label: typedSlot.label || slotId,\n icon: typedSlot.icon,\n order: typedSlot.order ?? 999,\n path: `/agents/${slug}/${slotId}`,\n requiredPermission: `manage:${slotId}`,\n };\n })\n .sort((a, b) => a.order - b.order);\n\n // Derive component declarations from package.json exports\n const components: AgentComponentDeclaration[] = [];\n if (packageName && packageJson?.exports) {\n for (const [exportKey, exportValue] of Object.entries(\n packageJson.exports,\n )) {\n // Match patterns like './admin', './town', etc.\n if (exportKey === '.' || exportKey === './manifest') continue;\n\n // Check if this export has a svelte condition (component export)\n const hasSvelteCondition = this.hasSvelteExport(exportValue);\n if (hasSvelteCondition) {\n const type = exportKey.replace('./', '');\n components.push({\n exportPath: `${packageName}/${type}`,\n type,\n });\n }\n }\n }\n\n // Capture adminRoutes from static property (same pattern as uiSlots)\n const adminRoutes: AgentAdminRouteManifest[] =\n (obj.staticProperties?.adminRoutes as\n | AgentAdminRouteManifest[]\n | undefined) ?? [];\n\n // Capture createEntries (agent-contributed create options)\n const createEntries: AgentCreateEntryManifest[] =\n (obj.staticProperties?.createEntries as\n | AgentCreateEntryManifest[]\n | undefined) ?? [];\n\n // Capture signalSubscriptions from static property\n const signalSubscriptions: string[] =\n (obj.staticProperties?.signalSubscriptions as string[] | undefined) ??\n [];\n\n const agentManifest: AgentManifest = {\n name: obj.className,\n slug,\n icon: agentConfig.icon,\n tier: agentConfig.tier || 'free',\n description: agentConfig.description,\n uiSlots,\n ...(adminRoutes.length > 0 ? { adminRoutes } : {}),\n ...(createEntries.length > 0 ? { createEntries } : {}),\n ...(signalSubscriptions.length > 0 ? { signalSubscriptions } : {}),\n permissions,\n features,\n menuItems,\n components,\n };\n\n obj.agent = agentManifest;\n\n logger.debug(\n `[manifest-generator] Generated agent manifest for ${obj.className}: ` +\n `${permissions.length} permissions, ${features.length} features, ` +\n `${menuItems.length} menu items, ${components.length} components`,\n );\n }\n }\n\n /**\n * Get deduplicated list of method names exposed via CLI and MCP config\n */\n private getExposedMethods(obj: SmartObjectDefinition): string[] {\n const methods = new Set<string>();\n\n const cliConfig = obj.decoratorConfig.cli;\n if (cliConfig && typeof cliConfig === 'object' && cliConfig.include) {\n for (const m of cliConfig.include) {\n methods.add(m);\n }\n }\n\n const mcpConfig = obj.decoratorConfig.mcp;\n if (mcpConfig && typeof mcpConfig === 'object' && mcpConfig.include) {\n for (const m of mcpConfig.include) {\n methods.add(m);\n }\n }\n\n return Array.from(methods);\n }\n\n /**\n * Check if an export value has a svelte condition (indicating a component export)\n */\n private hasSvelteExport(exportValue: unknown): boolean {\n if (!exportValue || typeof exportValue !== 'object') return false;\n\n // Check for { svelte: ... } condition\n if ('svelte' in exportValue) return true;\n\n // Check nested conditions like { import: { svelte: ... } }\n for (const val of Object.values(exportValue)) {\n if (val && typeof val === 'object' && 'svelte' in (val as object)) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Save manifest to file\n */\n saveManifest(manifest: SmartObjectManifest, filePath: string): void {\n const fs = require('node:fs');\n fs.writeFileSync(filePath, JSON.stringify(manifest, null, 2));\n }\n\n /**\n * Load manifest from file\n */\n loadManifest(filePath: string): SmartObjectManifest {\n const fs = require('node:fs');\n const content = fs.readFileSync(filePath, 'utf-8');\n return JSON.parse(content);\n }\n}\n\n/**\n * Convenience function to generate manifest\n *\n * @param scanResults - Array of scan results containing object definitions\n * @param options - Optional configuration (passed to ManifestGenerator.generateManifest)\n */\nexport function generateManifest(\n scanResults: ScanResult[],\n options?: {\n packageName?: string;\n packageVersion?: string;\n packageJson?: PackageJsonLike;\n smrtDependencies?: string[];\n includeVisibility?: SmrtVisibility[];\n },\n): SmartObjectManifest {\n const generator = new ManifestGenerator();\n return generator.generateManifest(scanResults, options);\n}\n"],"mappings":"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"}
|