@happyvertical/smrt-core 0.36.7 → 0.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/child-accessors.d.ts +1 -1
  2. package/dist/child-accessors.d.ts.map +1 -1
  3. package/dist/child-accessors.js +1 -1
  4. package/dist/child-accessors.js.map +1 -1
  5. package/dist/class.d.ts.map +1 -1
  6. package/dist/class.js +3 -1
  7. package/dist/class.js.map +1 -1
  8. package/dist/collection-cache.d.ts.map +1 -1
  9. package/dist/collection-cache.js +5 -3
  10. package/dist/collection-cache.js.map +1 -1
  11. package/dist/collection.d.ts +39 -16
  12. package/dist/collection.d.ts.map +1 -1
  13. package/dist/collection.js +40 -19
  14. package/dist/collection.js.map +1 -1
  15. package/dist/decorators/compatibility.d.ts +1 -1
  16. package/dist/decorators/compatibility.d.ts.map +1 -1
  17. package/dist/decorators/compatibility.js.map +1 -1
  18. package/dist/decorators/index.d.ts +4 -4
  19. package/dist/decorators/index.d.ts.map +1 -1
  20. package/dist/decorators/index.js.map +1 -1
  21. package/dist/hierarchical.d.ts.map +1 -1
  22. package/dist/hierarchical.js.map +1 -1
  23. package/dist/junction.d.ts.map +1 -1
  24. package/dist/junction.js.map +1 -1
  25. package/dist/manifest/static-manifest.d.ts.map +1 -1
  26. package/dist/manifest/static-manifest.js +39 -20
  27. package/dist/manifest/static-manifest.js.map +1 -1
  28. package/dist/manifest/store.js +2 -2
  29. package/dist/manifest/store.js.map +1 -1
  30. package/dist/manifest/test-manifest-stub.d.ts.map +1 -1
  31. package/dist/manifest/test-manifest-stub.js +2301 -629
  32. package/dist/manifest/test-manifest-stub.js.map +1 -1
  33. package/dist/manifest.json +39 -20
  34. package/dist/object.d.ts +64 -17
  35. package/dist/object.d.ts.map +1 -1
  36. package/dist/object.js +76 -30
  37. package/dist/object.js.map +1 -1
  38. package/dist/registry/class-registration.d.ts +3 -3
  39. package/dist/registry/class-registration.d.ts.map +1 -1
  40. package/dist/registry/class-registration.js +39 -42
  41. package/dist/registry/class-registration.js.map +1 -1
  42. package/dist/registry/inheritance-resolver.d.ts +17 -3
  43. package/dist/registry/inheritance-resolver.d.ts.map +1 -1
  44. package/dist/registry/inheritance-resolver.js +1 -1
  45. package/dist/registry/inheritance-resolver.js.map +1 -1
  46. package/dist/registry/manifest-field-merge.d.ts +17 -3
  47. package/dist/registry/manifest-field-merge.d.ts.map +1 -1
  48. package/dist/registry/manifest-field-merge.js +8 -6
  49. package/dist/registry/manifest-field-merge.js.map +1 -1
  50. package/dist/registry/schema-builder.d.ts +1 -1
  51. package/dist/registry/schema-builder.d.ts.map +1 -1
  52. package/dist/registry/schema-builder.js.map +1 -1
  53. package/dist/registry/shared-state.d.ts +3 -3
  54. package/dist/registry/shared-state.d.ts.map +1 -1
  55. package/dist/registry/shared-state.js.map +1 -1
  56. package/dist/registry/types.d.ts +78 -19
  57. package/dist/registry/types.d.ts.map +1 -1
  58. package/dist/registry/validator.d.ts +2 -1
  59. package/dist/registry/validator.d.ts.map +1 -1
  60. package/dist/registry/validator.js +38 -39
  61. package/dist/registry/validator.js.map +1 -1
  62. package/dist/registry.d.ts +84 -57
  63. package/dist/registry.d.ts.map +1 -1
  64. package/dist/registry.js +31 -25
  65. package/dist/registry.js.map +1 -1
  66. package/dist/runtime/client.d.ts +6 -6
  67. package/dist/runtime/client.d.ts.map +1 -1
  68. package/dist/runtime/client.js.map +1 -1
  69. package/dist/runtime/mcp.d.ts +11 -4
  70. package/dist/runtime/mcp.d.ts.map +1 -1
  71. package/dist/runtime/mcp.js.map +1 -1
  72. package/dist/runtime/server.d.ts +29 -5
  73. package/dist/runtime/server.d.ts.map +1 -1
  74. package/dist/runtime/server.js +4 -4
  75. package/dist/runtime/server.js.map +1 -1
  76. package/dist/runtime/types.d.ts +12 -12
  77. package/dist/runtime/types.d.ts.map +1 -1
  78. package/dist/smrt-knowledge.json +5 -4
  79. package/dist/system-fields.d.ts +1 -1
  80. package/dist/system-fields.d.ts.map +1 -1
  81. package/dist/system-fields.js.map +1 -1
  82. package/package.json +4 -4
@@ -1,8 +1,8 @@
1
- import { SmrtCollection } from '../collection';
2
1
  import { SmrtObject } from '../object';
2
+ import { SmartObjectDefinition } from '../scanner/types.js';
3
3
  import { RegisteredClass, SmartObjectConfig } from './types.js';
4
4
  export declare function register(ctor: typeof SmrtObject, config?: SmartObjectConfig): void;
5
- export declare function registerCollection(objectName: string, collectionConstructor: new (options: any) => SmrtCollection<any>): void;
5
+ export declare function registerCollection(objectName: string, collectionConstructor: NonNullable<RegisteredClass['collectionConstructor']>): void;
6
6
  /**
7
7
  * Invalidate cached inheritance state (chain + inheritedFields +
8
8
  * inheritedMethods) on `existing` AND every descendant whose `extends` or
@@ -27,5 +27,5 @@ export declare function invalidateInheritanceEntries(existing: RegisteredClass,
27
27
  name?: string;
28
28
  qualifiedName?: string;
29
29
  }): void;
30
- export declare function registerFromManifest(name: string, objectDef: any, packageName?: string): void;
30
+ export declare function registerFromManifest(name: string, objectDef: SmartObjectDefinition, packageName?: string): void;
31
31
  //# sourceMappingURL=class-registration.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"class-registration.d.ts","sourceRoot":"","sources":["../../src/registry/class-registration.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AASpD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAkCvC,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EAElB,MAAM,YAAY,CAAC;AAqapB,wBAAgB,QAAQ,CACtB,IAAI,EAAE,OAAO,UAAU,EACvB,MAAM,GAAE,iBAAsB,GAC7B,IAAI,CAomBN;AAED,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,EAClB,qBAAqB,EAAE,KAAK,OAAO,EAAE,GAAG,KAAK,cAAc,CAAC,GAAG,CAAC,GAC/D,IAAI,CAON;AA8ID;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,eAAe,EACzB,gBAAgB,CAAC,EAAE;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GACA,IAAI,CA2CN;AA+ID,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,GAAG,EACd,WAAW,CAAC,EAAE,MAAM,GACnB,IAAI,CAsQN"}
1
+ {"version":3,"file":"class-registration.d.ts","sourceRoot":"","sources":["../../src/registry/class-registration.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAUH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,KAAK,EAKV,qBAAqB,EAEtB,MAAM,qBAAqB,CAAC;AAqC7B,OAAO,KAAK,EACV,eAAe,EAEf,iBAAiB,EAElB,MAAM,YAAY,CAAC;AAqapB,wBAAgB,QAAQ,CACtB,IAAI,EAAE,OAAO,UAAU,EACvB,MAAM,GAAE,iBAAsB,GAC7B,IAAI,CAgnBN;AAED,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,EAMlB,qBAAqB,EAAE,WAAW,CAAC,eAAe,CAAC,uBAAuB,CAAC,CAAC,GAC3E,IAAI,CAeN;AA0LD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,eAAe,EACzB,gBAAgB,CAAC,EAAE;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GACA,IAAI,CA2CN;AA0ID,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,qBAAqB,EAChC,WAAW,CAAC,EAAE,MAAM,GACnB,IAAI,CAmQN"}
@@ -393,33 +393,35 @@ function register(ctor, config = {}) {
393
393
  `[registry] Applying ${decorators.size} field decorators for ${name}`
394
394
  );
395
395
  for (const [fieldName, decoratorOptions] of decorators) {
396
+ const opts = decoratorOptions;
396
397
  const existingField = fields.get(fieldName);
397
398
  if (existingField) {
399
+ const mergedMeta = {
400
+ ...existingField._meta,
401
+ ...decoratorOptions
402
+ };
398
403
  const mergedField = {
399
- type: decoratorOptions.type || existingField.type,
400
- _meta: {
401
- ...existingField._meta,
402
- ...decoratorOptions
403
- }
404
+ type: opts.type || existingField.type,
405
+ _meta: mergedMeta
404
406
  };
405
- if (mergedField._meta.type) {
406
- delete mergedField._meta.type;
407
+ if (mergedMeta.type) {
408
+ delete mergedMeta.type;
407
409
  }
408
- if (decoratorOptions.transient !== void 0) {
409
- mergedField.transient = decoratorOptions.transient;
410
+ if (opts.transient !== void 0) {
411
+ mergedField.transient = opts.transient;
410
412
  } else if (existingField.transient !== void 0) {
411
413
  mergedField.transient = existingField.transient;
412
414
  }
413
- if (decoratorOptions.nullable === true) {
415
+ if (opts.nullable === true) {
414
416
  mergedField.required = false;
415
- mergedField._meta.required = false;
416
- } else if (decoratorOptions.required !== void 0) {
417
- mergedField.required = decoratorOptions.required;
417
+ mergedMeta.required = false;
418
+ } else if (opts.required !== void 0) {
419
+ mergedField.required = opts.required;
418
420
  } else if (existingField.required !== void 0) {
419
421
  mergedField.required = existingField.required;
420
422
  }
421
- if (decoratorOptions.related !== void 0) {
422
- mergedField.related = decoratorOptions.related;
423
+ if (opts.related !== void 0) {
424
+ mergedField.related = opts.related;
423
425
  delete mergedField._meta?.related;
424
426
  } else if (existingField.related !== void 0) {
425
427
  mergedField.related = existingField.related;
@@ -429,26 +431,27 @@ function register(ctor, config = {}) {
429
431
  `[registry] ✅ Merged decorator for ${fieldName}: type=${mergedField.type}`
430
432
  );
431
433
  } else {
434
+ const newMeta = decoratorOptions;
432
435
  const newField = {
433
- type: decoratorOptions.type || "text",
434
- _meta: decoratorOptions
436
+ type: opts.type || "text",
437
+ _meta: newMeta
435
438
  };
436
- if (decoratorOptions.transient !== void 0) {
437
- newField.transient = decoratorOptions.transient;
439
+ if (opts.transient !== void 0) {
440
+ newField.transient = opts.transient;
438
441
  }
439
- if (decoratorOptions.nullable === true) {
442
+ if (opts.nullable === true) {
440
443
  newField.required = false;
441
- newField._meta.required = false;
442
- } else if (decoratorOptions.required !== void 0) {
443
- newField.required = decoratorOptions.required;
444
+ newMeta.required = false;
445
+ } else if (opts.required !== void 0) {
446
+ newField.required = opts.required;
444
447
  }
445
- if (decoratorOptions.related !== void 0) {
446
- newField.related = decoratorOptions.related;
448
+ if (opts.related !== void 0) {
449
+ newField.related = opts.related;
447
450
  delete newField._meta?.related;
448
451
  }
449
452
  fields.set(fieldName, newField);
450
453
  verboseLog(
451
- `[registry] ✅ Added field ${fieldName} from decorator: type=${decoratorOptions.type || "text"}`
454
+ `[registry] ✅ Added field ${fieldName} from decorator: type=${opts.type || "text"}`
452
455
  );
453
456
  }
454
457
  }
@@ -480,10 +483,9 @@ function register(ctor, config = {}) {
480
483
  methods.set(methodName, methodDef);
481
484
  }
482
485
  }
483
- if (config._manifestMethods) {
484
- for (const [methodName, methodDef] of Object.entries(
485
- config._manifestMethods
486
- )) {
486
+ const manifestMethods = config._manifestMethods;
487
+ if (manifestMethods) {
488
+ for (const [methodName, methodDef] of Object.entries(manifestMethods)) {
487
489
  methods.set(methodName, methodDef);
488
490
  }
489
491
  verboseLog(
@@ -652,7 +654,10 @@ function registerCollection(objectName, collectionConstructor) {
652
654
  if (registered) {
653
655
  registered.collectionConstructor = collectionConstructor;
654
656
  }
655
- getCollections().set(objectName, collectionConstructor);
657
+ getCollections().set(
658
+ objectName,
659
+ collectionConstructor
660
+ );
656
661
  }
657
662
  function normalizeTenantScopedConfig(tenantScoped) {
658
663
  if (!tenantScoped) {
@@ -794,10 +799,7 @@ function mergeManifestIntoExistingRegistration(existing, objectDef, packageName)
794
799
  tableName: manifestTableName
795
800
  };
796
801
  if (objectDef.fields) {
797
- for (const [fieldName, fieldDef] of Object.entries(
798
- objectDef.fields
799
- )) {
800
- const fd = fieldDef;
802
+ for (const [fieldName, fd] of Object.entries(objectDef.fields)) {
801
803
  if (!existing.fields.has(fieldName)) {
802
804
  existing.fields.set(fieldName, createFieldFromManifest(fd));
803
805
  continue;
@@ -817,9 +819,7 @@ function mergeManifestIntoExistingRegistration(existing, objectDef, packageName)
817
819
  ensureTenantScopedField(existing.fields, tenantScopedConfig);
818
820
  }
819
821
  if (objectDef.methods) {
820
- for (const [methodName, methodDef] of Object.entries(
821
- objectDef.methods
822
- )) {
822
+ for (const [methodName, methodDef] of Object.entries(objectDef.methods)) {
823
823
  existing.methods.set(methodName, methodDef);
824
824
  }
825
825
  }
@@ -940,10 +940,7 @@ function registerFromManifest(name, objectDef, packageName) {
940
940
  const fields = /* @__PURE__ */ new Map();
941
941
  const decorators = getFieldDecorators().get(simpleClassName);
942
942
  if (objectDef.fields) {
943
- for (const [fieldName, fieldDef] of Object.entries(
944
- objectDef.fields
945
- )) {
946
- const fd = fieldDef;
943
+ for (const [fieldName, fd] of Object.entries(objectDef.fields)) {
947
944
  fields.set(fieldName, createFieldFromManifest(fd));
948
945
  }
949
946
  }
@@ -1 +1 @@
1
- {"version":3,"file":"class-registration.js","sources":["../../src/registry/class-registration.ts"],"sourcesContent":["/**\n * Class registration module for the SMRT ObjectRegistry.\n *\n * Handles registering classes, collections, and manifest entries.\n *\n * Extracted from registry.ts as part of issue #1006.\n * @see https://github.com/happyvertical/smrt/issues/1006\n */\n\nimport type { SmrtCollection } from '../collection';\nimport { ConfigurationError } from '../errors';\nimport {\n discoverManifestSync,\n discoverSTISiblingsSync,\n getPackageName,\n lookupInManifest,\n} from '../manifest/manifest-loader.js';\nimport { cloneManifestSchemaColumns } from '../manifest/store.js';\nimport { SmrtObject } from '../object';\nimport type { QualifiedClassName, SmrtVisibility } from '../scanner/types.js';\nimport type { ColumnDefinition, SchemaDefinition } from '../schema/types.js';\nimport { tableNameFromClass, toSnakeCase } from '../utils';\nimport {\n createQualifiedName,\n isQualifiedName,\n} from '../utils/qualified-names.js';\nimport {\n type CollisionInputs,\n decideCollisionPolicy,\n type MatchKind,\n} from './collision-policy.js';\nimport { buildInheritanceChain } from './inheritance-resolver';\nimport {\n createFieldFromManifest,\n mergeManifestField,\n} from './manifest-field-merge.js';\nimport {\n findClass,\n getCanonicalClassName,\n hasClassCaseInsensitive,\n qualifyExtendsName,\n} from './name-resolver';\nimport {\n getClasses,\n getCollections,\n getConstructorIndex,\n getFieldDecorators,\n getInheritanceCache,\n getSourceFileFromStack,\n getStiSiblingsLoaded,\n verboseLog,\n} from './shared-state';\nimport type {\n RegisteredClass,\n SmartObjectConfig,\n ValidatorFunction,\n} from './types.js';\nimport { compileValidators } from './validator';\n\n/**\n * Compute the pluralized endpoint/collection name from a class name, using\n * the SAME simple inflection rules as the scanner's manifest adapter\n * (`packages/scanner/src/manifest-adapter.ts`). Used only as a fallback when\n * a registered class has no manifest-provided `collection` (e.g. inline test\n * classes registered purely via the decorator path). Keep in sync with the\n * scanner; the manifest value is always preferred when present. (smrt#1311.)\n *\n * Currency -> currencies (y -> ies)\n * CompanyResearch -> companyresearches (ch -> ches)\n * SourceCrawl -> sourcecrawls (+ s)\n * EmploymentPerson -> employmentpersons (naive + s, NOT \"people\")\n */\nfunction pluralizeCollection(className: string): string {\n const lower = className.toLowerCase();\n if (lower.endsWith('y')) return `${lower.slice(0, -1)}ies`;\n if (lower.endsWith('s') || lower.endsWith('x') || lower.endsWith('z')) {\n return `${lower}es`;\n }\n if (lower.endsWith('ch') || lower.endsWith('sh')) return `${lower}es`;\n return `${lower}s`;\n}\n\n/**\n * Shared bundled-context detector. Source files in these output\n * directories come from a bundler (Vite library mode, webpack, Next.js,\n * Nuxt, svelte-kit) that can duplicate module code across chunks.\n */\nfunction isBundledOutputPath(sourceFile: string | undefined): boolean {\n if (!sourceFile) return false;\n return (\n sourceFile.includes('.svelte-kit/output/') ||\n sourceFile.includes('/dist/') ||\n sourceFile.includes('/build/') ||\n sourceFile.includes('.next/') ||\n sourceFile.includes('.nuxt/')\n );\n}\n\n/**\n * Build `CollisionInputs` for the decorator-origin path (`register()`).\n * Manifest-origin inputs are built separately inside `registerFromManifest`.\n */\nfunction buildDecoratorCollisionInputs(args: {\n ctor: typeof SmrtObject;\n name: string;\n newPackageName: string | undefined;\n newSourceFile: string | undefined;\n newInBundledContext: boolean;\n existing: RegisteredClass;\n existingKey: string;\n matchKind: MatchKind;\n}): CollisionInputs {\n const {\n ctor,\n name,\n newPackageName,\n newSourceFile,\n newInBundledContext,\n existing,\n existingKey,\n matchKind,\n } = args;\n\n let newExtendsExisting = false;\n let existingExtendsNew = false;\n try {\n newExtendsExisting = ctor.prototype instanceof existing.constructor;\n existingExtendsNew = existing.constructor.prototype instanceof ctor;\n } catch {\n // `instanceof` can throw for non-function constructors. Keep both false.\n }\n\n const bothSourceFilesKnown = !!(newSourceFile && existing.sourceFilePath);\n const sameSourceFile =\n bothSourceFilesKnown && newSourceFile === existing.sourceFilePath;\n const existingIsPackageQualified = !!existing.packageName?.startsWith('@');\n const samePackage =\n !!newPackageName &&\n !!existing.packageName &&\n newPackageName === existing.packageName;\n const hasNewQualifiedKey = !!newPackageName;\n const existingKeyIsQualified = isQualifiedName(existingKey);\n\n return {\n origin: 'decorator',\n matchKind,\n sameConstructor: existing.constructor === ctor,\n sameSourceFile,\n bothSourceFilesKnown,\n existingIsManifestStub:\n (existing.constructor as { _isManifestStub?: boolean })\n ._isManifestStub === true,\n newInBundledContext,\n newExtendsExisting,\n existingExtendsNew,\n samePackage,\n existingIsPackageQualified,\n sameName: name === existing.name,\n hasNewQualifiedKey,\n existingKeyIsQualified,\n existingHasAnyPackage: !!existing.packageName,\n // Manifest-only fields; filled with safe defaults for decorator origin.\n hasManifestContent: false,\n registrationKeyDiffersFromExistingKey: false,\n existingHasNoPackage: !existing.packageName,\n };\n}\n\n/**\n * Execute the collision policy for `register()`. Returns `true` if the\n * policy resolved the collision (caller should return from `register`);\n * `false` means no policy match (the decision table is exhaustive so\n * that never actually happens — the default row throws).\n *\n * All state mutation (`upsertExistingEntry`, verboseLog) stays in this\n * caller-side helper; the policy function itself is pure.\n */\nfunction applyRegisterCollisionPolicy(args: {\n ctor: typeof SmrtObject;\n name: string;\n newPackageName: string | undefined;\n newSourceFile: string | undefined;\n newInBundledContext: boolean;\n existing: RegisteredClass;\n existingKey: string;\n matchKind: MatchKind;\n upsertExistingEntry: (\n existingKey: string,\n existing: RegisteredClass,\n ) => string;\n}): boolean {\n const inputs = buildDecoratorCollisionInputs(args);\n const decision = decideCollisionPolicy(inputs);\n\n switch (decision.policy) {\n case 'accept':\n case 'replace': {\n // Both map to the same operation for the decorator path:\n // update the existing slot's constructor + metadata. `replace`\n // only differs in verboseLog flavor so a reviewer reading the log\n // can tell which scenario fired.\n const newKey = args.upsertExistingEntry(args.existingKey, args.existing);\n if (\n decision.scenario === 'sti-child-wins' ||\n decision.scenario === 'manifest-stub-replacement'\n ) {\n verboseLog(\n `[registry] ${decision.scenario}: '${args.name}' → key='${newKey}' (${decision.reason})`,\n );\n }\n return true;\n }\n case 'skip':\n verboseLog(\n `[registry] ${decision.scenario}: skipping '${args.name}' (${decision.reason})`,\n );\n return true;\n case 'throw': {\n const matchSuffix =\n args.matchKind === 'case-insensitive'\n ? ` (case-insensitive match with \"${args.existingKey}\")`\n : '';\n throw new Error(\n `SMRT Class Name Collision: \"${args.name}\"${matchSuffix}\\n\\n` +\n `A class with this name is already registered, but with a different constructor.\\n` +\n `This usually happens when:\\n` +\n ` 1. Multiple test files define classes with the same name\\n` +\n ` 2. Different packages export classes with the same name\\n\\n` +\n `The collision will cause the wrong field definitions to be used,\\n` +\n `leading to properties not being initialized correctly.\\n\\n` +\n `To fix:\\n` +\n ` - Use unique class names (e.g., ${args.name}_UniqueId)\\n` +\n ` - Or use @smrt({ name: 'unique_name' }) to override the registration name`,\n );\n }\n case 'merge-manifest':\n case 'coexist-qualified':\n // These policies are only reachable from the manifest path; if we\n // somehow get here from `register()`, something is miswired.\n throw new Error(\n `decideCollisionPolicy returned '${decision.policy}' for decorator origin (scenario: ${decision.scenario}). This is a bug.`,\n );\n }\n}\n\n/**\n * Build `CollisionInputs` for the manifest-origin path\n * (`registerFromManifest`). Manifest entries have string-based inheritance\n * (`objectDef.extends`) rather than prototype-based, and no real\n * constructor to compare — `sameConstructor` is always false here.\n */\nfunction buildManifestCollisionInputs(args: {\n name: string;\n objectDef: any;\n packageName: string | undefined;\n existing: RegisteredClass;\n existingKey: string;\n registrationKey: string;\n matchKind: MatchKind;\n}): CollisionInputs {\n const {\n name,\n objectDef,\n packageName,\n existing,\n existingKey,\n registrationKey,\n matchKind,\n } = args;\n const newClassName = objectDef.className || name;\n const newExtends = objectDef.extends as string | undefined;\n\n // When an incoming manifest's `extends` points at the existing entry,\n // OR the existing entry's `extends` points at the incoming class, we\n // have an STI inheritance relationship. Each side checks:\n // - the simple name of the other\n // - the key under which the other is registered\n // - a case-insensitive fallback\n //\n // The `existingKey` comparison is load-bearing for cross-package STI:\n // `existing.extends` is stored post-`qualifyExtendsName()`, so it may\n // be the fully-qualified parent key like `@pkg:Parent`. Without this\n // comparison, `existingExtendsNew` falsely reads as false and the\n // arriving parent manifest would be registered as a duplicate instead\n // of skipped. See the deep-review report on #1140 for the fix rationale.\n const newExtendsExisting = !!(\n newExtends &&\n (newExtends === existing.name ||\n newExtends === existingKey ||\n newExtends.toLowerCase() === existing.name.toLowerCase())\n );\n const existingExtendsNew = !!(\n existing.extends &&\n (existing.extends === newClassName ||\n existing.extends === name ||\n existing.extends === registrationKey ||\n existing.extends.toLowerCase() === newClassName.toLowerCase())\n );\n\n const newSourceFile = objectDef.filePath as string | undefined;\n const bothSourceFilesKnown = !!(newSourceFile && existing.sourceFilePath);\n const sameSourceFile =\n bothSourceFilesKnown && newSourceFile === existing.sourceFilePath;\n const existingIsPackageQualified = !!existing.packageName?.startsWith('@');\n const samePackage =\n !!packageName &&\n !!existing.packageName &&\n packageName === existing.packageName;\n\n return {\n origin: 'manifest',\n matchKind,\n sameConstructor: false,\n sameSourceFile,\n bothSourceFilesKnown,\n existingIsManifestStub:\n (existing.constructor as { _isManifestStub?: boolean })\n ._isManifestStub === true,\n newInBundledContext: false,\n newExtendsExisting,\n existingExtendsNew,\n samePackage,\n existingIsPackageQualified,\n sameName: newClassName === existing.name,\n hasNewQualifiedKey: isQualifiedName(registrationKey),\n existingKeyIsQualified: isQualifiedName(existingKey),\n existingHasAnyPackage: !!existing.packageName,\n hasManifestContent: !!(\n objectDef.fields ||\n objectDef.methods ||\n objectDef.schema ||\n objectDef.decoratorConfig\n ),\n registrationKeyDiffersFromExistingKey: registrationKey !== existingKey,\n existingHasNoPackage: !existing.packageName,\n };\n // Note: manifest-origin sets hasNewQualifiedKey from the final\n // registrationKey (not packageName) because registerFromManifest accepts\n // an objectDef.qualifiedName fallback when packageName is omitted —\n // deriving from packageName alone would miss that case and misroute the\n // coexistence rows. See PR #1140 review (Copilot P1 at line 287).\n}\n\n/**\n * Execute the collision policy for `registerFromManifest()`. Returns\n * `'return'` when the policy fully resolves the collision (caller should\n * early-return from `registerFromManifest`) or `'continue'` when the new\n * registration should proceed to the fresh-entry code below the collision\n * block (either a child-wins delete-then-register or a different-package\n * coexist-qualified scenario).\n *\n * Implements the `merge-manifest` contract end-to-end: fold fields via\n * `mergeManifestIntoExistingRegistration`, then conditionally alias the\n * existing entry under `registrationKey` when it differs from the\n * canonical key — both steps preserve `issue-951:144-200`.\n */\nfunction applyManifestCollisionPolicy(args: {\n name: string;\n objectDef: any;\n packageName: string | undefined;\n existing: RegisteredClass;\n existingKey: string;\n registrationKey: string;\n matchKind: MatchKind;\n}): 'return' | 'continue' {\n const inputs = buildManifestCollisionInputs(args);\n const decision = decideCollisionPolicy(inputs);\n\n switch (decision.policy) {\n case 'skip':\n verboseLog(\n `[registry] ${decision.scenario}: skipping manifest '${args.name}' (${decision.reason})`,\n );\n return 'return';\n case 'replace':\n // STI child-wins: delete existing so the new entry can register fresh.\n getClasses().delete(args.existingKey);\n verboseLog(\n `[registry] ${decision.scenario}: '${args.name}' replaces '${args.existingKey}' (${decision.reason})`,\n );\n return 'continue';\n case 'merge-manifest': {\n mergeManifestIntoExistingRegistration(\n args.existing,\n args.objectDef,\n args.packageName,\n );\n if (args.registrationKey !== args.existingKey) {\n const classes = getClasses();\n classes.set(args.registrationKey, args.existing);\n getConstructorIndex().set(\n args.existing.constructor,\n args.registrationKey,\n );\n }\n return 'return';\n }\n case 'coexist-qualified':\n // Both registrations live under their qualified keys; caller falls\n // through to register the new one fresh.\n return 'continue';\n case 'accept':\n // Manifest origin never returns 'accept' (that's a decorator-path\n // policy). Treat defensively as return-no-op.\n return 'return';\n case 'throw':\n // Manifest collisions default to skip, never throw — this branch is\n // unreachable from the manifest origin. Guard against future drift.\n throw new Error(\n `decideCollisionPolicy returned 'throw' for manifest origin (scenario: ${decision.scenario}). This is a bug.`,\n );\n }\n}\n\nfunction resolveTableName(\n ctor: typeof SmrtObject,\n name: string,\n config: SmartObjectConfig,\n): string {\n const manifestEntry = config._manifest\n ? lookupInManifest(config._manifest, name)\n : discoverManifestSync(name);\n\n return (\n manifestEntry?.schema?.tableName ||\n manifestEntry?.decoratorConfig?.tableName ||\n config.tableName ||\n tableNameFromClass(ctor)\n );\n}\n\nfunction setSmrtTableName(ctor: typeof SmrtObject, tableName: string): void {\n const existing = Object.getOwnPropertyDescriptor(ctor, 'SMRT_TABLE_NAME');\n if (existing?.value === tableName) {\n return;\n }\n\n Object.defineProperty(ctor, 'SMRT_TABLE_NAME', {\n value: tableName,\n writable: false,\n enumerable: false,\n configurable: true,\n });\n}\n\n/**\n * Attach the registry's qualified name to the constructor as a static\n * property. Mirrors the `SMRT_TABLE_NAME` pattern.\n *\n * Survives:\n * - Minification (the property is set on the constructor itself).\n * - HMR / module duplication / federated-module boundaries where the\n * `constructorIndex` WeakMap holds an older constructor identity than\n * the one a caller has in hand.\n *\n * Acts as a belt-and-suspenders fallback for runtime code that has a\n * constructor reference and wants its registry identity without going\n * through a Map lookup (e.g. `SmrtHierarchical._hierarchyCollection`).\n */\nfunction setSmrtQualifiedName(\n ctor: typeof SmrtObject,\n qualifiedName: string | undefined,\n): void {\n if (!qualifiedName) return;\n const existing = Object.getOwnPropertyDescriptor(ctor, '_smrtQualifiedName');\n if (existing?.value === qualifiedName) {\n return;\n }\n\n Object.defineProperty(ctor, '_smrtQualifiedName', {\n value: qualifiedName,\n writable: false,\n enumerable: false,\n configurable: true,\n });\n}\n\nexport function register(\n ctor: typeof SmrtObject,\n config: SmartObjectConfig = {},\n): void {\n const name = config.name || ctor.name;\n const explicitPackageName = config.packageName;\n\n function upsertExistingEntry(\n existingKey: string,\n existing: RegisteredClass,\n ): string {\n const nextPackageName = explicitPackageName || existing.packageName;\n const nextKey = nextPackageName\n ? createQualifiedName(nextPackageName, name)\n : name;\n // Capture pre-mutation identity so descendants whose `extends` still\n // references the old name/qualifiedName are caught by the post-mutation\n // invalidation sweep (#1139 Gap 2).\n const previousIdentity = {\n name: existing.name,\n qualifiedName: existing.qualifiedName as string | undefined,\n };\n\n existing.name = name;\n existing.packageName = nextPackageName;\n existing.qualifiedName = nextPackageName\n ? (createQualifiedName(nextPackageName, name) as QualifiedClassName)\n : undefined;\n const nextTableName = resolveTableName(ctor, name, {\n ...existing.config,\n ...config,\n });\n existing.config = {\n ...existing.config,\n ...config,\n tableName: nextTableName,\n };\n if (!existing.schema) {\n existing.schema = {\n ddl: '',\n indexes: [],\n triggers: [],\n tableName: nextTableName,\n columns: {},\n foreignKeys: [],\n dependencies: [],\n version: '',\n };\n }\n existing.schema.tableName = nextTableName;\n existing.constructor = ctor;\n setSmrtTableName(ctor, nextTableName);\n setSmrtQualifiedName(ctor, existing.qualifiedName);\n\n if (existingKey !== nextKey) {\n const classes = getClasses();\n const existingAtNextKey = classes.get(nextKey);\n\n if (existingAtNextKey && existingAtNextKey !== existing) {\n throw new ConfigurationError(\n `Class registry collision while promoting \"${existingKey}\" to \"${nextKey}\". ` +\n 'A different class is already registered under the target key.',\n 'CONFIG_REGISTRY_PROMOTION_COLLISION',\n {\n existingKey,\n nextKey,\n className: name,\n },\n );\n }\n\n classes.delete(existingKey);\n classes.set(nextKey, existing);\n }\n\n getConstructorIndex().set(ctor, nextKey);\n\n // Release C follow-up #1139 Gap 2: we just mutated `existing.name`,\n // `existing.packageName`, `existing.qualifiedName`, `existing.config`,\n // `existing.constructor`, and `existing.schema.tableName`. Any\n // descendant whose cached `inheritedFields` was computed against the\n // prior identity now carries stale data. Invalidate `existing` and\n // every descendant whose `extends` matches the pre- or post-mutation\n // identity so the next field read re-merges from the current state.\n invalidateInheritanceEntries(existing, previousIdentity);\n\n return nextKey;\n }\n\n // Release C (#1134): collision resolution for both exact-match and\n // case-insensitive paths now routes through decideCollisionPolicy, which\n // consolidates the 11-branch if/else tree from pre-C.\n const newSourceFile = getSourceFileFromStack();\n const newPackageName =\n explicitPackageName || getPackageName(ctor, true) || undefined;\n const newInBundledContext = isBundledOutputPath(newSourceFile);\n\n // 1. Exact-match check (existingKey === name)\n if (getClasses().has(name)) {\n const existing = getClasses().get(name);\n if (!existing) {\n throw new Error(\n `Registry inconsistency: ${name} exists in classes Map but get() returned undefined`,\n );\n }\n\n const handled = applyRegisterCollisionPolicy({\n ctor,\n name,\n newPackageName,\n newSourceFile,\n newInBundledContext,\n existing,\n existingKey: name,\n matchKind: 'exact-key',\n upsertExistingEntry,\n });\n if (handled) return;\n }\n\n // 2. Case-insensitive check for manifest stubs (Issue #531, #847) and\n // other same-name-different-case collisions.\n const lowerName = name.toLowerCase();\n for (const [existingKey, existing] of getClasses().entries()) {\n const keyMatches = existingKey.toLowerCase() === lowerName;\n const nameMatches = existing.name?.toLowerCase() === lowerName;\n if (!(keyMatches || nameMatches) || existingKey === name) continue;\n\n const handled = applyRegisterCollisionPolicy({\n ctor,\n name,\n newPackageName,\n newSourceFile,\n newInBundledContext,\n existing,\n existingKey,\n matchKind: 'case-insensitive',\n upsertExistingEntry,\n });\n if (handled) return;\n }\n\n // CRITICAL: Capture package name NOW, while stack trace still shows external package\n // This is called from the @smrt() decorator during import, so the stack trace\n // includes the external package file path. Later calls won't have this context.\n // Skip registry check to avoid circular dependency - class isn't registered yet!\n // This solves issue #159 where external package manifests couldn't be loaded.\n const packageNameFromStack =\n explicitPackageName || getPackageName(ctor, true) || undefined;\n\n // Capture source file path for collision detection during module re-evaluation\n // (Issue #555: Test isolation - class name collision during vitest collection)\n const sourceFilePath = getSourceFileFromStack();\n\n // Get field definitions from manifest\n // Priority order (Issue #270 Phase 1 - synchronous manifest loading):\n // 1. Explicitly provided manifest (_manifest parameter)\n // 2. Test manifests (for test classes)\n // 3. Static manifests (for core framework classes)\n // 4. Cached external manifests (if already loaded)\n // For external packages not yet loaded, manifest discovery happens lazily during schema generation\n // Issue #713: Use lookupInManifest for qualified name support\n let manifestEntry: ReturnType<typeof lookupInManifest> | undefined;\n if (config._manifest) {\n manifestEntry = lookupInManifest(config._manifest, name);\n }\n if (!manifestEntry) {\n manifestEntry = discoverManifestSync(name);\n }\n const fields = new Map<string, any>();\n const methods = new Map<string, any>();\n let packageName: string | undefined;\n\n verboseLog(\n `[registry] Registering ${name}: manifestEntry =`,\n manifestEntry ? 'found' : 'not found',\n );\n if (manifestEntry?.fields) {\n verboseLog(\n `[registry] Manifest has ${Object.keys(manifestEntry.fields).length} fields:`,\n Object.keys(manifestEntry.fields),\n );\n }\n\n if (manifestEntry?.fields) {\n // Use manifest fields (from build-time AST scanning)\n // Store field definitions as plain objects with nested options\n for (const [fieldName, fieldDef] of Object.entries(\n manifestEntry.fields,\n ) as [string, import('../scanner/types.js').FieldDefinition][]) {\n // Build options object, only including defined values\n const options: any = { ...fieldDef._meta };\n if (fieldDef.required !== undefined) options.required = fieldDef.required;\n if (fieldDef.default !== undefined) options.default = fieldDef.default;\n if (fieldDef.description !== undefined)\n options.description = fieldDef.description;\n if (fieldDef.transient !== undefined)\n options.transient = fieldDef.transient;\n\n // Store field definition as plain object maintaining Field-like structure\n const field: any = {\n type: fieldDef.type,\n };\n\n // Only include options if not empty\n if (Object.keys(options).length > 0) {\n field._meta = options;\n }\n\n // Preserve top-level flags from manifest\n if (fieldDef.transient !== undefined) {\n field.transient = fieldDef.transient;\n }\n if (fieldDef.required !== undefined) {\n field.required = fieldDef.required;\n }\n\n // Hoist related to top level for relationship fields\n // Check both fieldDef.related (new manifests) and _meta.related (old manifests)\n if (fieldDef.related !== undefined) {\n field.related = fieldDef.related;\n } else if (options.related !== undefined) {\n field.related = options.related;\n delete field._meta?.related;\n }\n\n fields.set(fieldName, field);\n }\n\n verboseLog(\n `[registry] ✅ Loaded ${fields.size} fields for ${name} from manifest`,\n );\n\n // Use packageName from manifest if available, otherwise from stack trace\n // Priority: explicit manifest > manifestEntry > stack trace\n packageName =\n explicitPackageName ||\n config._manifest?.packageName ||\n manifestEntry.packageName ||\n packageNameFromStack;\n } else {\n // No manifest found yet - use package name from stack trace\n // This will be used later by ensureManifestLoaded() to load the external manifest\n verboseLog(\n `[registry] ⚠️ No manifest entry for ${name} - fields will be loaded later`,\n );\n packageName = packageNameFromStack;\n }\n\n // Apply decorator metadata to override/extend manifest fields\n // Decorators take priority over AST-scanned types (Issue #316)\n const decorators = getFieldDecorators().get(name);\n if (decorators && decorators.size > 0) {\n verboseLog(\n `[registry] Applying ${decorators.size} field decorators for ${name}`,\n );\n\n for (const [fieldName, decoratorOptions] of decorators) {\n const existingField = fields.get(fieldName);\n\n if (existingField) {\n // Merge decorator options with manifest field\n // Decorator type takes priority over AST-scanned type\n const mergedField: any = {\n type: decoratorOptions.type || existingField.type,\n _meta: {\n ...existingField._meta,\n ...decoratorOptions,\n },\n };\n\n // Remove 'type' from _meta if it was moved to top level\n if (mergedField._meta.type) {\n delete mergedField._meta.type;\n }\n\n // Preserve top-level flags (transient, required, etc.)\n if (decoratorOptions.transient !== undefined) {\n mergedField.transient = decoratorOptions.transient;\n } else if (existingField.transient !== undefined) {\n mergedField.transient = existingField.transient;\n }\n\n // Handle required flag: nullable fields should not be required\n if (decoratorOptions.nullable === true) {\n // Nullable explicitly set to true means field is NOT required\n mergedField.required = false;\n mergedField._meta.required = false;\n } else if (decoratorOptions.required !== undefined) {\n mergedField.required = decoratorOptions.required;\n } else if (existingField.required !== undefined) {\n mergedField.required = existingField.required;\n }\n\n // Hoist related to top level for relationship fields\n if (decoratorOptions.related !== undefined) {\n mergedField.related = decoratorOptions.related;\n delete mergedField._meta?.related;\n } else if (existingField.related !== undefined) {\n mergedField.related = existingField.related;\n }\n\n fields.set(fieldName, mergedField);\n verboseLog(\n `[registry] ✅ Merged decorator for ${fieldName}: type=${mergedField.type}`,\n );\n } else {\n // Decorator for field not in manifest - add it\n const newField: any = {\n type: decoratorOptions.type || 'text',\n _meta: decoratorOptions,\n };\n\n // Set top-level flags from decorator options\n if (decoratorOptions.transient !== undefined) {\n newField.transient = decoratorOptions.transient;\n }\n // Handle required flag: nullable fields should not be required\n if (decoratorOptions.nullable === true) {\n newField.required = false;\n newField._meta.required = false;\n } else if (decoratorOptions.required !== undefined) {\n newField.required = decoratorOptions.required;\n }\n\n // Hoist related to top level for relationship fields (Issue #746)\n // This is critical for getRelationshipMap() to detect relationships\n if (decoratorOptions.related !== undefined) {\n newField.related = decoratorOptions.related;\n delete newField._meta?.related;\n }\n\n fields.set(fieldName, newField);\n verboseLog(\n `[registry] ✅ Added field ${fieldName} from decorator: type=${decoratorOptions.type || 'text'}`,\n );\n }\n }\n }\n\n // Handle tenantScoped configuration (Issue #688)\n // External manifests can carry tenantScoped only in decoratorConfig, so\n // registration must honor the merged view rather than only explicit config.\n let tenantScopedConfig: RegisteredClass['tenantScopedConfig'] | undefined;\n const effectiveTenantScoped =\n config.tenantScoped ?? manifestEntry?.decoratorConfig?.tenantScoped;\n if (effectiveTenantScoped) {\n // Normalize boolean or object config into full options\n const tenantOpts =\n typeof effectiveTenantScoped === 'boolean' ? {} : effectiveTenantScoped;\n tenantScopedConfig = {\n mode: tenantOpts.mode ?? 'required',\n field: tenantOpts.field ?? 'tenantId',\n autoFilter: tenantOpts.autoFilter ?? true,\n autoPopulate: tenantOpts.autoPopulate ?? true,\n allowSuperAdminBypass: tenantOpts.allowSuperAdminBypass ?? false,\n };\n\n // Inject or enrich tenantId field\n const fieldName = tenantScopedConfig.field;\n const hadTenantField = fields.has(fieldName);\n ensureTenantScopedField(fields, tenantScopedConfig);\n if (!hadTenantField) {\n verboseLog(\n `[registry] ✅ Injected ${fieldName} field for tenant-scoped class ${name}`,\n );\n }\n }\n\n if (manifestEntry?.methods) {\n // Load method definitions from manifest (for custom CLI/API/MCP generation)\n for (const [methodName, methodDef] of Object.entries(\n manifestEntry.methods,\n )) {\n methods.set(methodName, methodDef);\n }\n }\n\n // Also load methods from _manifestMethods in config (from consumer plugin register.js)\n // This is how external package methods are passed to the registry\n if ((config as any)._manifestMethods) {\n for (const [methodName, methodDef] of Object.entries(\n (config as any)._manifestMethods,\n )) {\n methods.set(methodName, methodDef);\n }\n verboseLog(\n `[registry] Loaded ${methods.size} methods for ${name} from _manifestMethods`,\n );\n }\n\n // Note: If manifest not found here, it will be loaded asynchronously when needed\n // via ensureManifestLoaded(). This allows decorators to remain synchronous while\n // supporting dynamic external package manifest loading.\n\n // Build inheritance chain from constructor (needed for STI table name resolution)\n const inheritanceChain = buildInheritanceChain(ctor);\n\n // Validate table strategy compatibility with parent (STI requirement)\n if (inheritanceChain.length > 1) {\n // This class has a parent - validate strategy compatibility\n const parentName = inheritanceChain[inheritanceChain.length - 2]; // Second-to-last is parent\n const parentEntry = findClass(parentName);\n\n if (parentEntry) {\n const parentStrategy = parentEntry.config?.tableStrategy || 'default';\n const childStrategy = config.tableStrategy; // Don't default - undefined means inherit\n\n // Only validate if child has an EXPLICIT strategy that differs from parent\n // undefined childStrategy means it will inherit from parent\n if (childStrategy !== undefined && parentStrategy !== childStrategy) {\n throw ConfigurationError.incompatibleStrategy(\n name,\n childStrategy,\n parentName,\n parentStrategy,\n );\n }\n }\n }\n\n // Defer schema generation until needed (generateSchema now uses dynamic import)\n // Store table name for lazy schema generation\n // Priority for STI: manifest's tableName > decorator config > derived from class name\n // The manifest's tableName is computed at build-time when full class hierarchy is known,\n // which correctly handles STI inheritance. The decorator may derive wrong tableName\n // if parent class isn't registered yet at decorator execution time.\n const tableName = resolveTableName(ctor, name, config);\n setSmrtTableName(ctor, tableName);\n\n // Load pre-generated schema from manifest if available, otherwise placeholder\n let schema: SchemaDefinition;\n if (manifestEntry?.schema) {\n // Pre-generated schema from manifest (build-time)\n // Keep indexes as IndexDefinition objects for DDL strategies\n schema = {\n ddl: manifestEntry.schema.ddl,\n indexes:\n manifestEntry.schema.indexes?.map((idx: any) => ({\n name: idx.name,\n columns: idx.columns || [],\n unique: idx.unique || false,\n where: idx.where,\n description: idx.description,\n jsonPath: idx.jsonPath,\n })) || [],\n triggers: [],\n tableName: manifestEntry.schema.tableName || tableName,\n // Cast manifest columns to ColumnDefinition (same shape, TypeScript just needs help)\n columns: cloneManifestSchemaColumns(manifestEntry.schema.columns),\n foreignKeys: [],\n dependencies: [],\n version: manifestEntry.schema.version || '',\n packageName: manifestEntry.packageName,\n };\n verboseLog(\n `[registry] Loaded pre-generated schema for ${name} (${Object.keys(manifestEntry.schema.columns || {}).length} columns)`,\n );\n } else {\n // Placeholder schema - will be generated lazily when first needed\n schema = {\n ddl: '', // Generated lazily\n indexes: [], // Parsed from DDL lazily\n triggers: [], // No longer using database triggers - timestamps managed by application\n tableName,\n columns: {},\n foreignKeys: [],\n dependencies: [],\n version: '',\n packageName: undefined,\n };\n }\n\n if (schema.columns) {\n applySqlTypeOverrides(schema.columns, fields.entries());\n if (decorators && decorators.size > 0) {\n applySqlTypeOverrides(schema.columns, decorators.entries());\n }\n }\n\n // Use pre-computed validation rules from manifest if available (Issue #782)\n // For decorator-based registration, manifest may have pre-computed rules\n const validationRules = manifestEntry?.validationRules;\n let validators: ValidatorFunction[] | undefined;\n\n // Only compile validators if no pre-computed rules exist\n if (!validationRules || validationRules.length === 0) {\n validators = compileValidators(name, fields);\n } else {\n verboseLog(\n `[registry] Using ${validationRules.length} pre-computed validation rules for ${name}`,\n );\n }\n\n // Derive extends from prototype chain if not available from manifest\n // This is critical for inline test classes that use decorators\n let extendsClass: string | undefined = manifestEntry?.extends;\n if (!extendsClass) {\n const proto = Object.getPrototypeOf(ctor);\n if (proto?.name && proto.name !== 'SmrtObject' && proto.name !== 'Object') {\n extendsClass = proto.name;\n }\n }\n\n // Merge manifest's decoratorConfig into config\n // Use the computed tableName which prioritizes manifest's value for STI correctness\n const mergedConfig = {\n ...manifestEntry?.decoratorConfig,\n ...config,\n tableName, // Override with correctly computed tableName\n };\n\n // Generate qualified name if we have a package name\n // Format: \"@package/name:ClassName\"\n const qualifiedName = packageName\n ? createQualifiedName(packageName, name)\n : undefined;\n\n // Determine visibility from config, manifest, or default to 'public'\n // Priority: explicit config > manifest > default\n const visibility: SmrtVisibility =\n config.visibility || manifestEntry?.visibility || 'public';\n\n // Issue #951: Use qualified name as primary key when available\n const registrationKey = qualifiedName || name;\n\n getClasses().set(registrationKey, {\n name,\n qualifiedName, // Qualified name for cross-package identification\n constructor: ctor,\n config: mergedConfig,\n fields,\n methods,\n schema,\n validators,\n validationRules, // Pre-computed rules from manifest (Issue #782)\n tools: manifestEntry?.tools, // AI-callable tool schemas (CLI param schemas)\n // Pluralized endpoint name. Prefer the manifest's computed value (handles\n // STI inheritance + any future inflection changes); fall back to the same\n // simple pluralization the scanner uses for inline/test classes that have\n // no manifest entry. (smrt#1311.)\n collection: manifestEntry?.collection ?? pluralizeCollection(name),\n packageName, // Store package name from manifest for getPackageName() lookup\n sourceFilePath, // Store source file for collision detection (Issue #555)\n extends: extendsClass, // Capture parent class name from manifest OR prototype chain\n extendsTypeArg: manifestEntry?.extendsTypeArg, // SmrtCollection<T> generic arg\n tenantScopedConfig, // Multi-tenancy config (Issue #688)\n visibility, // Visibility control for manifest filtering\n // NOTE: Don't pre-compute inheritanceChain here - let getInheritanceChain() compute\n // it lazily using the `extends` field. This ensures correct chain for both\n // decorator-registered and manifest-loaded classes.\n });\n\n // Release B (#1133): case-insensitive lookups iterate the classes Map\n // directly instead of maintaining a parallel classNameMap index.\n\n // Index constructor for O(1) reverse lookups (Issue #713: constructor-based lookup)\n getConstructorIndex().set(ctor, registrationKey);\n // Stamp the qualified name on the constructor itself as a fallback for\n // runtime code that has a constructor reference but might hit a\n // WeakMap miss (HMR / federated modules / multiple-copy edge cases).\n setSmrtQualifiedName(ctor, qualifiedName);\n\n verboseLog(\n `🎯 Registered smrt object: ${name} (key: ${registrationKey}) with schema for ${schema.tableName} and ${(validators?.length || 0) + (validationRules?.length || 0)} validators/rules`,\n );\n\n // STI sibling auto-loading (Issue #430)\n // When a class is registered that shares a table with other classes (STI),\n // we need to discover and register ALL siblings so that getAllSchemas()\n // can merge columns from all subtypes for the database adapter.\n //\n // IMPORTANT: Only auto-load siblings from EXTERNAL packages.\n // For test classes or classes in the same package, they will be registered\n // by their own @smrt() decorators. Auto-loading them as stubs would cause collisions.\n const collection = manifestEntry?.collection;\n if (collection && !getStiSiblingsLoaded().has(collection)) {\n // Mark this collection as processed to prevent infinite recursion\n getStiSiblingsLoaded().add(collection);\n\n verboseLog(\n `[registry] Checking for STI siblings for collection: ${collection}`,\n );\n\n // Discover all classes that share this collection (table)\n const siblings = discoverSTISiblingsSync(collection);\n\n // Register any siblings that aren't already registered\n // Only load siblings from DIFFERENT packages to avoid collisions with local classes\n for (const sibling of siblings) {\n // Use case-insensitive check to prevent registering 'Praeco' when 'praeco' exists\n if (!hasClassCaseInsensitive(sibling.className)) {\n // Skip siblings from the same package - they will be registered by their own decorators\n if (\n sibling.packageName &&\n packageName &&\n sibling.packageName === packageName\n ) {\n verboseLog(\n `[registry] Skipping STI sibling ${sibling.className} from same package: ${packageName}`,\n );\n continue;\n }\n\n verboseLog(\n `[registry] Auto-loading STI sibling: ${sibling.className} for collection: ${collection}`,\n );\n registerFromManifest(\n sibling.className,\n sibling.entry,\n sibling.packageName,\n );\n }\n }\n }\n}\n\nexport function registerCollection(\n objectName: string,\n collectionConstructor: new (options: any) => SmrtCollection<any>,\n): void {\n const registered = findClass(objectName);\n if (registered) {\n registered.collectionConstructor = collectionConstructor;\n }\n\n getCollections().set(objectName, collectionConstructor as any);\n}\n\n// resolveManifestCollision was removed in Release C (#1134). Its three-branch\n// decision is now represented as explicit rows in the collision-policy\n// decision table — see `manifest-same-source-file`, `manifest-sti-child-wins`,\n// `manifest-sti-parent-skip`, `manifest-default-skip` scenarios in\n// packages/core/src/registry/collision-policy.ts.\n\nfunction normalizeTenantScopedConfig(\n tenantScoped: any,\n): RegisteredClass['tenantScopedConfig'] | undefined {\n if (!tenantScoped) {\n return undefined;\n }\n\n const tenantOpts = typeof tenantScoped === 'boolean' ? {} : tenantScoped;\n return {\n mode: tenantOpts.mode ?? 'required',\n field: tenantOpts.field ?? 'tenantId',\n autoFilter: tenantOpts.autoFilter ?? true,\n autoPopulate: tenantOpts.autoPopulate ?? true,\n allowSuperAdminBypass: tenantOpts.allowSuperAdminBypass ?? false,\n };\n}\n\nfunction ensureTenantScopedField(\n fields: Map<string, any>,\n tenantScopedConfig: RegisteredClass['tenantScopedConfig'] | undefined,\n): void {\n if (!tenantScopedConfig) {\n return;\n }\n\n const fieldName = tenantScopedConfig.field;\n const existingField = fields.get(fieldName);\n if (existingField) {\n fields.set(fieldName, {\n ...existingField,\n required:\n existingField.required ?? tenantScopedConfig.mode === 'required',\n _meta: {\n ...existingField._meta,\n reference: existingField._meta?.reference ?? 'Tenant',\n sqlType: 'UUID',\n __tenancy: {\n ...existingField._meta?.__tenancy,\n isTenantIdField: true,\n ...tenantScopedConfig,\n },\n },\n });\n return;\n }\n\n fields.set(fieldName, {\n type: 'foreignKey',\n related: 'Tenant',\n required: tenantScopedConfig.mode === 'required',\n _meta: {\n reference: 'Tenant',\n sqlType: 'UUID',\n __tenancy: {\n isTenantIdField: true,\n ...tenantScopedConfig,\n },\n },\n });\n}\n\nfunction mergeIndexDefinitions(\n existingIndexes: Array<any> | undefined,\n manifestIndexes: Array<any> | undefined,\n): Array<any> {\n const merged = [...(existingIndexes || [])];\n const seen = new Set(merged.map((index) => index?.name).filter(Boolean));\n\n for (const index of manifestIndexes || []) {\n if (!index?.name || seen.has(index.name)) {\n continue;\n }\n merged.push(index);\n seen.add(index.name);\n }\n\n return merged;\n}\n\n// cloneManifestSchemaColumns lives in ../manifest/store.ts — imported above.\n// (Hoisted out of the duplicate definition here and in registry.ts.)\n\nfunction getReferenceKindFromFieldOptions(\n fieldOptions: any,\n): ColumnDefinition['referenceKind'] | undefined {\n if (\n fieldOptions?.__tenancy?.isTenantIdField ||\n fieldOptions?._meta?.__tenancy?.isTenantIdField\n ) {\n return 'tenantId';\n }\n\n if (fieldOptions?.type === 'foreignKey') {\n return 'foreignKey';\n }\n\n if (fieldOptions?.type === 'crossPackageRef') {\n return 'crossPackageRef';\n }\n\n return undefined;\n}\n\nfunction applySqlTypeOverrides(\n columns: Record<string, ColumnDefinition>,\n fieldEntries: Iterable<[string, any]> | undefined,\n): void {\n if (!fieldEntries) {\n return;\n }\n\n for (const [fieldName, fieldOptions] of fieldEntries) {\n const sqlType = fieldOptions?.sqlType ?? fieldOptions?._meta?.sqlType;\n const referenceKind = getReferenceKindFromFieldOptions(fieldOptions);\n if (!sqlType && !referenceKind) {\n continue;\n }\n\n const columnName = toSnakeCase(fieldName);\n const existingColumn = columns[columnName];\n if (!existingColumn) {\n continue;\n }\n\n columns[columnName] = {\n ...existingColumn,\n ...(sqlType\n ? { type: String(sqlType).toUpperCase() as ColumnDefinition['type'] }\n : {}),\n ...(referenceKind ? { referenceKind } : {}),\n };\n }\n}\n\n/**\n * Invalidate cached inheritance state (chain + inheritedFields +\n * inheritedMethods) on `existing` AND every descendant whose `extends` or\n * `inheritanceChain` references it.\n *\n * This covers both simple-name and qualified-name `extends` matches, which\n * is why `ObjectRegistry.invalidateInheritanceCache` delegates here (Release\n * C follow-up #1139 Gap 1 — the old recursive public helper only matched\n * `extends === className` by exact string, silently missing qualified\n * descendants like `@pkg:Parent`).\n *\n * `previousIdentity` is used by `upsertExistingEntry` (Gap 2): when a class\n * is promoted (its name/packageName/qualifiedName are mutated in place),\n * descendants registered against the pre-mutation identity need to be\n * invalidated too. Pass the pre-mutation `{ name, qualifiedName }` so this\n * sweep matches against both the old and new identity.\n *\n * Exported for the public `ObjectRegistry.invalidateInheritanceCache`\n * shim in registry.ts.\n */\nexport function invalidateInheritanceEntries(\n existing: RegisteredClass,\n previousIdentity?: {\n name?: string;\n qualifiedName?: string;\n },\n): void {\n const cache = getInheritanceCache();\n const affectedNames = new Set<string>();\n\n const remember = (name: string | undefined): void => {\n if (name) {\n affectedNames.add(name);\n }\n };\n\n const matchNames = new Set<string>();\n const rememberMatch = (name: string | undefined): void => {\n if (name) matchNames.add(name);\n };\n rememberMatch(existing.name);\n rememberMatch(existing.qualifiedName);\n rememberMatch(previousIdentity?.name);\n rememberMatch(previousIdentity?.qualifiedName);\n\n for (const name of matchNames) {\n remember(name);\n }\n\n for (const [key, candidate] of getClasses()) {\n const extendsMatches =\n !!candidate.extends && matchNames.has(candidate.extends);\n const chainMatches =\n !!candidate.inheritanceChain &&\n candidate.inheritanceChain.some((n) => matchNames.has(n));\n\n if (candidate === existing || extendsMatches || chainMatches) {\n candidate.inheritanceChain = undefined;\n candidate.inheritedFields = undefined;\n candidate.inheritedMethods = undefined;\n remember(key);\n remember(candidate.name);\n remember(candidate.qualifiedName);\n }\n }\n\n for (const name of affectedNames) {\n cache.delete(name);\n }\n}\n\nfunction mergeManifestIntoExistingRegistration(\n existing: RegisteredClass,\n objectDef: any,\n packageName?: string,\n): void {\n const manifestConfig = objectDef.decoratorConfig || {};\n const manifestTableName =\n objectDef.schema?.tableName ||\n manifestConfig.tableName ||\n existing.schema?.tableName ||\n existing.config.tableName ||\n tableNameFromClass(existing.constructor);\n\n existing.config = {\n ...manifestConfig,\n ...existing.config,\n tableName: manifestTableName,\n };\n\n if (objectDef.fields) {\n for (const [fieldName, fieldDef] of Object.entries(\n objectDef.fields as Record<string, any>,\n )) {\n const fd = fieldDef as any;\n if (!existing.fields.has(fieldName)) {\n existing.fields.set(fieldName, createFieldFromManifest(fd));\n continue;\n }\n\n const existingField = existing.fields.get(fieldName);\n if (!existingField) {\n continue;\n }\n\n existing.fields.set(fieldName, mergeManifestField(existingField, fd));\n }\n }\n\n const tenantScopedConfig = normalizeTenantScopedConfig(\n existing.config.tenantScoped,\n );\n if (tenantScopedConfig) {\n existing.tenantScopedConfig = tenantScopedConfig;\n ensureTenantScopedField(existing.fields, tenantScopedConfig);\n }\n\n if (objectDef.methods) {\n for (const [methodName, methodDef] of Object.entries(\n objectDef.methods as Record<string, any>,\n )) {\n existing.methods.set(methodName, methodDef);\n }\n }\n\n if (objectDef.schema) {\n const manifestSchema: SchemaDefinition = {\n ddl: objectDef.schema.ddl || '',\n indexes:\n objectDef.schema.indexes?.map((idx: any) => ({\n name: idx.name,\n columns: idx.columns || [],\n unique: idx.unique || false,\n where: idx.where,\n description: idx.description,\n jsonPath: idx.jsonPath,\n })) || [],\n triggers: [],\n tableName: objectDef.schema.tableName || manifestTableName,\n columns: cloneManifestSchemaColumns(objectDef.schema.columns),\n foreignKeys: [],\n dependencies: [],\n version: objectDef.schema.version || '',\n packageName: packageName,\n };\n\n applySqlTypeOverrides(manifestSchema.columns, existing.fields.entries());\n\n existing.schema = {\n ...(existing.schema || {}),\n ...manifestSchema,\n tableName: manifestSchema.tableName,\n ddl: manifestSchema.ddl || existing.schema?.ddl || '',\n columns: {\n ...(existing.schema?.columns || {}),\n ...(manifestSchema.columns || {}),\n },\n indexes: mergeIndexDefinitions(\n existing.schema?.indexes,\n manifestSchema.indexes,\n ),\n packageName: packageName || existing.schema?.packageName,\n };\n } else if (!existing.schema) {\n existing.schema = {\n ddl: '',\n indexes: [],\n triggers: [],\n tableName: manifestTableName,\n columns: {},\n foreignKeys: [],\n dependencies: [],\n version: '',\n packageName: packageName,\n };\n } else {\n existing.schema.tableName = manifestTableName;\n existing.schema.packageName = packageName || existing.schema.packageName;\n }\n\n if (objectDef.validationRules !== undefined) {\n existing.validationRules = objectDef.validationRules;\n existing.validators = undefined;\n } else if (!existing.validationRules && !existing.validators) {\n existing.validators = compileValidators(existing.name, existing.fields);\n }\n\n if (packageName) {\n existing.packageName = packageName;\n existing.qualifiedName = createQualifiedName(\n packageName,\n existing.name,\n ) as QualifiedClassName;\n } else if (!existing.packageName && objectDef.packageName) {\n existing.packageName = objectDef.packageName;\n }\n\n if (objectDef.extends) {\n existing.extends = packageName\n ? qualifyExtendsName(objectDef.extends, packageName)\n : objectDef.extends;\n }\n\n if (!existing.sourceFilePath && objectDef.filePath) {\n existing.sourceFilePath = objectDef.filePath;\n }\n\n existing.visibility =\n objectDef.visibility || manifestConfig.visibility || existing.visibility;\n invalidateInheritanceEntries(existing);\n}\n\nexport function registerFromManifest(\n name: string,\n objectDef: any,\n packageName?: string,\n): void {\n // Issue #951: Compute simple class name and registration key early\n // `name` may be a qualified key from manifest (e.g., '@happyvertical/smrt-events:Event')\n // `simpleClassName` is always the plain class name (e.g., 'Event')\n const simpleClassName = objectDef.className || name;\n const qualifiedNameEarly = packageName\n ? createQualifiedName(packageName, simpleClassName)\n : (objectDef.qualifiedName as QualifiedClassName | undefined);\n const registrationKey = (qualifiedNameEarly || name) as string;\n\n // Release C (#1134): collision resolution routes through\n // decideCollisionPolicy. See collision-policy.ts for the 16-row decision\n // table; applyManifestCollisionPolicy below turns a policy into registry\n // mutations.\n //\n // Two collision checks, matching pre-C behavior:\n // 1. Canonical-name lookup (case-insensitive simple-name match; covers\n // issue #950's STI child-wins and issue #951's qualified coexistence).\n // 2. Exact-key match (handles re-registration with same qualified key).\n //\n // The ambiguous case (multiple existing entries share the simple name —\n // `getCanonicalClassName` returns undefined) is NOT fed through the table.\n // It falls through both checks into the new-registration code below,\n // preserving issue #951's coexistence semantics.\n const existingCanonical = getCanonicalClassName(simpleClassName);\n if (existingCanonical) {\n const existing = getClasses().get(existingCanonical);\n if (existing) {\n const outcome = applyManifestCollisionPolicy({\n name,\n objectDef,\n packageName,\n existing,\n existingKey: existingCanonical,\n registrationKey,\n matchKind: 'canonical-name',\n });\n if (outcome === 'return') return;\n // outcome === 'continue' means policy was replace (child-wins) or\n // coexist — fall through into the new-registration code below.\n }\n // else: stale map entry (key exists but class was removed) — allow registration\n }\n\n if (getClasses().has(registrationKey)) {\n const existing = getClasses().get(registrationKey);\n if (!existing) return;\n const outcome = applyManifestCollisionPolicy({\n name,\n objectDef,\n packageName,\n existing,\n existingKey: registrationKey,\n registrationKey,\n matchKind: 'exact-key',\n });\n if (outcome === 'return') return;\n }\n\n // Issue #1004: Qualify the `extends` value BEFORE inserting this class\n // into the classes Map. Otherwise qualifyExtendsName would iterate and\n // find the child's own entry, creating a circular extends chain\n // (e.g., @test/sports:TestEvent extends itself). Release B (#1133) swapped\n // the underlying classNameMap lookup for an iteration over `classes`, but\n // the ordering invariant still holds.\n const qualifiedExtends =\n objectDef.extends && packageName\n ? qualifyExtendsName(objectDef.extends, packageName)\n : objectDef.extends;\n\n // Release B (#1133): case-insensitive lookups iterate the classes Map\n // directly; no parallel classNameMap index to maintain.\n\n // Create stub constructor - not needed for CLI command generation\n // The CLI only needs metadata (fields, methods, config)\n // Mark as manifest stub so real class can replace it during decorator registration\n const stubConstructor = class extends SmrtObject {\n static readonly _isManifestStub = true;\n } as typeof SmrtObject;\n Object.defineProperty(stubConstructor, 'name', { value: simpleClassName });\n\n // Convert manifest field definitions to Field objects\n const fields = new Map<string, any>();\n const decorators = getFieldDecorators().get(simpleClassName);\n if (objectDef.fields) {\n for (const [fieldName, fieldDef] of Object.entries(\n objectDef.fields as any,\n )) {\n const fd = fieldDef as any;\n fields.set(fieldName, createFieldFromManifest(fd));\n }\n }\n\n // Load method definitions\n const methods = new Map<string, any>();\n if (objectDef.methods) {\n for (const [methodName, methodDef] of Object.entries(objectDef.methods)) {\n methods.set(methodName, methodDef);\n }\n }\n\n // Get config from manifest\n const config = objectDef.decoratorConfig || {};\n const tableName = config.tableName || tableNameFromClass(stubConstructor);\n\n // Load pre-generated schema from manifest if available\n // This enables efficient external package consumption without runtime schema generation\n let schema: SchemaDefinition;\n if (objectDef.schema) {\n // Pre-generated schema from manifest (build-time)\n // Keep indexes as IndexDefinition objects for DDL strategies\n schema = {\n ddl: objectDef.schema.ddl,\n indexes:\n objectDef.schema.indexes?.map((idx: any) => ({\n name: idx.name,\n columns: idx.columns || [],\n unique: idx.unique || false,\n where: idx.where,\n description: idx.description,\n jsonPath: idx.jsonPath,\n })) || [],\n triggers: [],\n tableName: objectDef.schema.tableName,\n columns: cloneManifestSchemaColumns(objectDef.schema.columns),\n foreignKeys: [],\n dependencies: [],\n version: objectDef.schema.version || '',\n packageName: packageName,\n };\n applySqlTypeOverrides(schema.columns, fields.entries());\n applySqlTypeOverrides(schema.columns, decorators?.entries());\n verboseLog(\n `[registry] Loaded pre-generated schema for ${name} (${Object.keys(objectDef.schema.columns || {}).length} columns)`,\n );\n } else {\n // Placeholder schema - will be generated at runtime if needed\n schema = {\n ddl: '',\n indexes: [],\n triggers: [],\n tableName,\n columns: {},\n foreignKeys: [],\n dependencies: [],\n version: '',\n packageName: packageName,\n };\n }\n\n // Use pre-computed validation rules from manifest if available (Issue #782)\n // This avoids compiling validator closures at runtime, reducing startup time\n const validationRules = objectDef.validationRules;\n let validators: ValidatorFunction[] | undefined;\n\n // Only compile validators if no pre-computed rules exist\n // (backward compatibility for older manifests)\n if (!validationRules || validationRules.length === 0) {\n validators = compileValidators(name, fields);\n verboseLog(\n `[registry] No pre-computed rules for ${name}, compiled ${validators.length} validators`,\n );\n } else {\n verboseLog(\n `[registry] Using ${validationRules.length} pre-computed validation rules for ${name}`,\n );\n }\n\n // Issue #951: Use qualifiedNameEarly computed at the top of this function\n // (uses simpleClassName, not the manifest key which may already be qualified)\n const qualifiedName = qualifiedNameEarly;\n\n // Get visibility from manifest (defaults to 'public')\n const visibility: SmrtVisibility =\n objectDef.visibility || config.visibility || 'public';\n\n // Register in ObjectRegistry (metadata only, no collection constructor)\n // Manifest registration is for command discovery and help text.\n // Runtime execution requires real classes loaded from entry point.\n //\n // Issue #847: Use className from objectDef (simple name like 'Council') for the name\n // property, not the qualified name key. This enables getFields() lookups by simple\n // class name to work correctly. simpleClassName is defined earlier in this function.\n //\n // Issue #951: Use registrationKey (qualified when available) as the primary key\n getClasses().set(registrationKey, {\n name: simpleClassName,\n qualifiedName, // Qualified name for cross-package identification\n constructor: stubConstructor,\n config,\n fields,\n methods,\n schema,\n validators,\n validationRules, // Pre-computed rules from manifest (Issue #782)\n tools: objectDef.tools, // AI-callable tool schemas (used for CLI param schemas)\n // Pluralized endpoint name; fall back to simple pluralization if a\n // (legacy) manifest lacks it. (smrt#1311.)\n collection: objectDef.collection ?? pluralizeCollection(simpleClassName),\n packageName,\n sourceFilePath: objectDef.filePath, // Store source file for collision detection (Issue #555)\n extends: qualifiedExtends, // Issue #1004: Pre-computed qualified parent\n extendsTypeArg: objectDef.extendsTypeArg, // SmrtCollection<T> generic arg\n visibility, // New: Visibility control for manifest filtering\n });\n // Tag the synthetic stub constructor with the qualified name so the\n // same constructor-side identity convention holds for manifest-loaded\n // classes as well as decorator-registered ones.\n setSmrtQualifiedName(stubConstructor, qualifiedName);\n\n verboseLog(\n `📦 Registered ${simpleClassName} from manifest (key: ${registrationKey}, ${fields.size} fields, ${methods.size} methods)`,\n );\n\n // STI sibling auto-loading (Issue #430)\n // When a class is registered that shares a table with other classes (STI),\n // we need to discover and register ALL siblings so that getAllSchemas()\n // can merge columns from all subtypes for the database adapter.\n //\n // IMPORTANT: Only auto-load siblings from EXTERNAL packages.\n // For test classes or classes in the same package, they will be registered\n // by their own @smrt() decorators. Auto-loading them as stubs would cause collisions.\n const collection = objectDef.collection;\n if (collection && !getStiSiblingsLoaded().has(collection)) {\n // Mark this collection as processed to prevent infinite recursion\n getStiSiblingsLoaded().add(collection);\n\n verboseLog(\n `[registry] Checking for STI siblings for collection: ${collection}`,\n );\n\n // Discover all classes that share this collection (table)\n const siblings = discoverSTISiblingsSync(collection);\n\n // Register any siblings that aren't already registered\n // Only load siblings from DIFFERENT packages to avoid collisions with local classes\n for (const sibling of siblings) {\n // Use case-insensitive check to prevent registering 'Praeco' when 'praeco' exists\n if (!hasClassCaseInsensitive(sibling.className)) {\n // Skip siblings from the same package - they will be registered by their own decorators\n if (\n sibling.packageName &&\n packageName &&\n sibling.packageName === packageName\n ) {\n verboseLog(\n `[registry] Skipping STI sibling ${sibling.className} from same package: ${packageName}`,\n );\n continue;\n }\n\n verboseLog(\n `[registry] Auto-loading STI sibling: ${sibling.className} for collection: ${collection}`,\n );\n registerFromManifest(\n sibling.className,\n sibling.entry,\n sibling.packageName,\n );\n }\n }\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"class-registration.js","sources":["../../src/registry/class-registration.ts"],"sourcesContent":["/**\n * Class registration module for the SMRT ObjectRegistry.\n *\n * Handles registering classes, collections, and manifest entries.\n *\n * Extracted from registry.ts as part of issue #1006.\n * @see https://github.com/happyvertical/smrt/issues/1006\n */\n\nimport { ConfigurationError } from '../errors';\nimport {\n discoverManifestSync,\n discoverSTISiblingsSync,\n getPackageName,\n lookupInManifest,\n} from '../manifest/manifest-loader.js';\nimport { cloneManifestSchemaColumns } from '../manifest/store.js';\nimport { SmrtObject } from '../object';\nimport type {\n FieldDefinition,\n FieldMeta,\n MethodDefinition,\n QualifiedClassName,\n SmartObjectDefinition,\n SmrtVisibility,\n} from '../scanner/types.js';\nimport type {\n ColumnDefinition,\n IndexDefinition,\n SchemaDefinition,\n} from '../schema/types.js';\nimport { tableNameFromClass, toSnakeCase } from '../utils';\nimport {\n createQualifiedName,\n isQualifiedName,\n} from '../utils/qualified-names.js';\nimport {\n type CollisionInputs,\n decideCollisionPolicy,\n type MatchKind,\n} from './collision-policy.js';\nimport { buildInheritanceChain } from './inheritance-resolver';\nimport {\n createFieldFromManifest,\n mergeManifestField,\n} from './manifest-field-merge.js';\nimport {\n findClass,\n getCanonicalClassName,\n hasClassCaseInsensitive,\n qualifyExtendsName,\n} from './name-resolver';\nimport {\n getClasses,\n getCollections,\n getConstructorIndex,\n getFieldDecorators,\n getInheritanceCache,\n getSourceFileFromStack,\n getStiSiblingsLoaded,\n verboseLog,\n} from './shared-state';\nimport type {\n RegisteredClass,\n RegisteredField,\n SmartObjectConfig,\n ValidatorFunction,\n} from './types.js';\nimport { compileValidators } from './validator';\n\n/**\n * Compute the pluralized endpoint/collection name from a class name, using\n * the SAME simple inflection rules as the scanner's manifest adapter\n * (`packages/scanner/src/manifest-adapter.ts`). Used only as a fallback when\n * a registered class has no manifest-provided `collection` (e.g. inline test\n * classes registered purely via the decorator path). Keep in sync with the\n * scanner; the manifest value is always preferred when present. (smrt#1311.)\n *\n * Currency -> currencies (y -> ies)\n * CompanyResearch -> companyresearches (ch -> ches)\n * SourceCrawl -> sourcecrawls (+ s)\n * EmploymentPerson -> employmentpersons (naive + s, NOT \"people\")\n */\nfunction pluralizeCollection(className: string): string {\n const lower = className.toLowerCase();\n if (lower.endsWith('y')) return `${lower.slice(0, -1)}ies`;\n if (lower.endsWith('s') || lower.endsWith('x') || lower.endsWith('z')) {\n return `${lower}es`;\n }\n if (lower.endsWith('ch') || lower.endsWith('sh')) return `${lower}es`;\n return `${lower}s`;\n}\n\n/**\n * Shared bundled-context detector. Source files in these output\n * directories come from a bundler (Vite library mode, webpack, Next.js,\n * Nuxt, svelte-kit) that can duplicate module code across chunks.\n */\nfunction isBundledOutputPath(sourceFile: string | undefined): boolean {\n if (!sourceFile) return false;\n return (\n sourceFile.includes('.svelte-kit/output/') ||\n sourceFile.includes('/dist/') ||\n sourceFile.includes('/build/') ||\n sourceFile.includes('.next/') ||\n sourceFile.includes('.nuxt/')\n );\n}\n\n/**\n * Build `CollisionInputs` for the decorator-origin path (`register()`).\n * Manifest-origin inputs are built separately inside `registerFromManifest`.\n */\nfunction buildDecoratorCollisionInputs(args: {\n ctor: typeof SmrtObject;\n name: string;\n newPackageName: string | undefined;\n newSourceFile: string | undefined;\n newInBundledContext: boolean;\n existing: RegisteredClass;\n existingKey: string;\n matchKind: MatchKind;\n}): CollisionInputs {\n const {\n ctor,\n name,\n newPackageName,\n newSourceFile,\n newInBundledContext,\n existing,\n existingKey,\n matchKind,\n } = args;\n\n let newExtendsExisting = false;\n let existingExtendsNew = false;\n try {\n newExtendsExisting = ctor.prototype instanceof existing.constructor;\n existingExtendsNew = existing.constructor.prototype instanceof ctor;\n } catch {\n // `instanceof` can throw for non-function constructors. Keep both false.\n }\n\n const bothSourceFilesKnown = !!(newSourceFile && existing.sourceFilePath);\n const sameSourceFile =\n bothSourceFilesKnown && newSourceFile === existing.sourceFilePath;\n const existingIsPackageQualified = !!existing.packageName?.startsWith('@');\n const samePackage =\n !!newPackageName &&\n !!existing.packageName &&\n newPackageName === existing.packageName;\n const hasNewQualifiedKey = !!newPackageName;\n const existingKeyIsQualified = isQualifiedName(existingKey);\n\n return {\n origin: 'decorator',\n matchKind,\n sameConstructor: existing.constructor === ctor,\n sameSourceFile,\n bothSourceFilesKnown,\n existingIsManifestStub:\n (existing.constructor as { _isManifestStub?: boolean })\n ._isManifestStub === true,\n newInBundledContext,\n newExtendsExisting,\n existingExtendsNew,\n samePackage,\n existingIsPackageQualified,\n sameName: name === existing.name,\n hasNewQualifiedKey,\n existingKeyIsQualified,\n existingHasAnyPackage: !!existing.packageName,\n // Manifest-only fields; filled with safe defaults for decorator origin.\n hasManifestContent: false,\n registrationKeyDiffersFromExistingKey: false,\n existingHasNoPackage: !existing.packageName,\n };\n}\n\n/**\n * Execute the collision policy for `register()`. Returns `true` if the\n * policy resolved the collision (caller should return from `register`);\n * `false` means no policy match (the decision table is exhaustive so\n * that never actually happens — the default row throws).\n *\n * All state mutation (`upsertExistingEntry`, verboseLog) stays in this\n * caller-side helper; the policy function itself is pure.\n */\nfunction applyRegisterCollisionPolicy(args: {\n ctor: typeof SmrtObject;\n name: string;\n newPackageName: string | undefined;\n newSourceFile: string | undefined;\n newInBundledContext: boolean;\n existing: RegisteredClass;\n existingKey: string;\n matchKind: MatchKind;\n upsertExistingEntry: (\n existingKey: string,\n existing: RegisteredClass,\n ) => string;\n}): boolean {\n const inputs = buildDecoratorCollisionInputs(args);\n const decision = decideCollisionPolicy(inputs);\n\n switch (decision.policy) {\n case 'accept':\n case 'replace': {\n // Both map to the same operation for the decorator path:\n // update the existing slot's constructor + metadata. `replace`\n // only differs in verboseLog flavor so a reviewer reading the log\n // can tell which scenario fired.\n const newKey = args.upsertExistingEntry(args.existingKey, args.existing);\n if (\n decision.scenario === 'sti-child-wins' ||\n decision.scenario === 'manifest-stub-replacement'\n ) {\n verboseLog(\n `[registry] ${decision.scenario}: '${args.name}' → key='${newKey}' (${decision.reason})`,\n );\n }\n return true;\n }\n case 'skip':\n verboseLog(\n `[registry] ${decision.scenario}: skipping '${args.name}' (${decision.reason})`,\n );\n return true;\n case 'throw': {\n const matchSuffix =\n args.matchKind === 'case-insensitive'\n ? ` (case-insensitive match with \"${args.existingKey}\")`\n : '';\n throw new Error(\n `SMRT Class Name Collision: \"${args.name}\"${matchSuffix}\\n\\n` +\n `A class with this name is already registered, but with a different constructor.\\n` +\n `This usually happens when:\\n` +\n ` 1. Multiple test files define classes with the same name\\n` +\n ` 2. Different packages export classes with the same name\\n\\n` +\n `The collision will cause the wrong field definitions to be used,\\n` +\n `leading to properties not being initialized correctly.\\n\\n` +\n `To fix:\\n` +\n ` - Use unique class names (e.g., ${args.name}_UniqueId)\\n` +\n ` - Or use @smrt({ name: 'unique_name' }) to override the registration name`,\n );\n }\n case 'merge-manifest':\n case 'coexist-qualified':\n // These policies are only reachable from the manifest path; if we\n // somehow get here from `register()`, something is miswired.\n throw new Error(\n `decideCollisionPolicy returned '${decision.policy}' for decorator origin (scenario: ${decision.scenario}). This is a bug.`,\n );\n }\n}\n\n/**\n * Build `CollisionInputs` for the manifest-origin path\n * (`registerFromManifest`). Manifest entries have string-based inheritance\n * (`objectDef.extends`) rather than prototype-based, and no real\n * constructor to compare — `sameConstructor` is always false here.\n */\nfunction buildManifestCollisionInputs(args: {\n name: string;\n objectDef: SmartObjectDefinition;\n packageName: string | undefined;\n existing: RegisteredClass;\n existingKey: string;\n registrationKey: string;\n matchKind: MatchKind;\n}): CollisionInputs {\n const {\n name,\n objectDef,\n packageName,\n existing,\n existingKey,\n registrationKey,\n matchKind,\n } = args;\n const newClassName = objectDef.className || name;\n const newExtends = objectDef.extends;\n\n // When an incoming manifest's `extends` points at the existing entry,\n // OR the existing entry's `extends` points at the incoming class, we\n // have an STI inheritance relationship. Each side checks:\n // - the simple name of the other\n // - the key under which the other is registered\n // - a case-insensitive fallback\n //\n // The `existingKey` comparison is load-bearing for cross-package STI:\n // `existing.extends` is stored post-`qualifyExtendsName()`, so it may\n // be the fully-qualified parent key like `@pkg:Parent`. Without this\n // comparison, `existingExtendsNew` falsely reads as false and the\n // arriving parent manifest would be registered as a duplicate instead\n // of skipped. See the deep-review report on #1140 for the fix rationale.\n const newExtendsExisting = !!(\n newExtends &&\n (newExtends === existing.name ||\n newExtends === existingKey ||\n newExtends.toLowerCase() === existing.name.toLowerCase())\n );\n const existingExtendsNew = !!(\n existing.extends &&\n (existing.extends === newClassName ||\n existing.extends === name ||\n existing.extends === registrationKey ||\n existing.extends.toLowerCase() === newClassName.toLowerCase())\n );\n\n const newSourceFile = objectDef.filePath;\n const bothSourceFilesKnown = !!(newSourceFile && existing.sourceFilePath);\n const sameSourceFile =\n bothSourceFilesKnown && newSourceFile === existing.sourceFilePath;\n const existingIsPackageQualified = !!existing.packageName?.startsWith('@');\n const samePackage =\n !!packageName &&\n !!existing.packageName &&\n packageName === existing.packageName;\n\n return {\n origin: 'manifest',\n matchKind,\n sameConstructor: false,\n sameSourceFile,\n bothSourceFilesKnown,\n existingIsManifestStub:\n (existing.constructor as { _isManifestStub?: boolean })\n ._isManifestStub === true,\n newInBundledContext: false,\n newExtendsExisting,\n existingExtendsNew,\n samePackage,\n existingIsPackageQualified,\n sameName: newClassName === existing.name,\n hasNewQualifiedKey: isQualifiedName(registrationKey),\n existingKeyIsQualified: isQualifiedName(existingKey),\n existingHasAnyPackage: !!existing.packageName,\n hasManifestContent: !!(\n objectDef.fields ||\n objectDef.methods ||\n objectDef.schema ||\n objectDef.decoratorConfig\n ),\n registrationKeyDiffersFromExistingKey: registrationKey !== existingKey,\n existingHasNoPackage: !existing.packageName,\n };\n // Note: manifest-origin sets hasNewQualifiedKey from the final\n // registrationKey (not packageName) because registerFromManifest accepts\n // an objectDef.qualifiedName fallback when packageName is omitted —\n // deriving from packageName alone would miss that case and misroute the\n // coexistence rows. See PR #1140 review (Copilot P1 at line 287).\n}\n\n/**\n * Execute the collision policy for `registerFromManifest()`. Returns\n * `'return'` when the policy fully resolves the collision (caller should\n * early-return from `registerFromManifest`) or `'continue'` when the new\n * registration should proceed to the fresh-entry code below the collision\n * block (either a child-wins delete-then-register or a different-package\n * coexist-qualified scenario).\n *\n * Implements the `merge-manifest` contract end-to-end: fold fields via\n * `mergeManifestIntoExistingRegistration`, then conditionally alias the\n * existing entry under `registrationKey` when it differs from the\n * canonical key — both steps preserve `issue-951:144-200`.\n */\nfunction applyManifestCollisionPolicy(args: {\n name: string;\n objectDef: SmartObjectDefinition;\n packageName: string | undefined;\n existing: RegisteredClass;\n existingKey: string;\n registrationKey: string;\n matchKind: MatchKind;\n}): 'return' | 'continue' {\n const inputs = buildManifestCollisionInputs(args);\n const decision = decideCollisionPolicy(inputs);\n\n switch (decision.policy) {\n case 'skip':\n verboseLog(\n `[registry] ${decision.scenario}: skipping manifest '${args.name}' (${decision.reason})`,\n );\n return 'return';\n case 'replace':\n // STI child-wins: delete existing so the new entry can register fresh.\n getClasses().delete(args.existingKey);\n verboseLog(\n `[registry] ${decision.scenario}: '${args.name}' replaces '${args.existingKey}' (${decision.reason})`,\n );\n return 'continue';\n case 'merge-manifest': {\n mergeManifestIntoExistingRegistration(\n args.existing,\n args.objectDef,\n args.packageName,\n );\n if (args.registrationKey !== args.existingKey) {\n const classes = getClasses();\n classes.set(args.registrationKey, args.existing);\n getConstructorIndex().set(\n args.existing.constructor,\n args.registrationKey,\n );\n }\n return 'return';\n }\n case 'coexist-qualified':\n // Both registrations live under their qualified keys; caller falls\n // through to register the new one fresh.\n return 'continue';\n case 'accept':\n // Manifest origin never returns 'accept' (that's a decorator-path\n // policy). Treat defensively as return-no-op.\n return 'return';\n case 'throw':\n // Manifest collisions default to skip, never throw — this branch is\n // unreachable from the manifest origin. Guard against future drift.\n throw new Error(\n `decideCollisionPolicy returned 'throw' for manifest origin (scenario: ${decision.scenario}). This is a bug.`,\n );\n }\n}\n\nfunction resolveTableName(\n ctor: typeof SmrtObject,\n name: string,\n config: SmartObjectConfig,\n): string {\n const manifestEntry = config._manifest\n ? lookupInManifest(config._manifest, name)\n : discoverManifestSync(name);\n\n return (\n manifestEntry?.schema?.tableName ||\n manifestEntry?.decoratorConfig?.tableName ||\n config.tableName ||\n tableNameFromClass(ctor)\n );\n}\n\nfunction setSmrtTableName(ctor: typeof SmrtObject, tableName: string): void {\n const existing = Object.getOwnPropertyDescriptor(ctor, 'SMRT_TABLE_NAME');\n if (existing?.value === tableName) {\n return;\n }\n\n Object.defineProperty(ctor, 'SMRT_TABLE_NAME', {\n value: tableName,\n writable: false,\n enumerable: false,\n configurable: true,\n });\n}\n\n/**\n * Attach the registry's qualified name to the constructor as a static\n * property. Mirrors the `SMRT_TABLE_NAME` pattern.\n *\n * Survives:\n * - Minification (the property is set on the constructor itself).\n * - HMR / module duplication / federated-module boundaries where the\n * `constructorIndex` WeakMap holds an older constructor identity than\n * the one a caller has in hand.\n *\n * Acts as a belt-and-suspenders fallback for runtime code that has a\n * constructor reference and wants its registry identity without going\n * through a Map lookup (e.g. `SmrtHierarchical._hierarchyCollection`).\n */\nfunction setSmrtQualifiedName(\n ctor: typeof SmrtObject,\n qualifiedName: string | undefined,\n): void {\n if (!qualifiedName) return;\n const existing = Object.getOwnPropertyDescriptor(ctor, '_smrtQualifiedName');\n if (existing?.value === qualifiedName) {\n return;\n }\n\n Object.defineProperty(ctor, '_smrtQualifiedName', {\n value: qualifiedName,\n writable: false,\n enumerable: false,\n configurable: true,\n });\n}\n\nexport function register(\n ctor: typeof SmrtObject,\n config: SmartObjectConfig = {},\n): void {\n const name = config.name || ctor.name;\n const explicitPackageName = config.packageName;\n\n function upsertExistingEntry(\n existingKey: string,\n existing: RegisteredClass,\n ): string {\n const nextPackageName = explicitPackageName || existing.packageName;\n const nextKey = nextPackageName\n ? createQualifiedName(nextPackageName, name)\n : name;\n // Capture pre-mutation identity so descendants whose `extends` still\n // references the old name/qualifiedName are caught by the post-mutation\n // invalidation sweep (#1139 Gap 2).\n const previousIdentity = {\n name: existing.name,\n qualifiedName: existing.qualifiedName as string | undefined,\n };\n\n existing.name = name;\n existing.packageName = nextPackageName;\n existing.qualifiedName = nextPackageName\n ? (createQualifiedName(nextPackageName, name) as QualifiedClassName)\n : undefined;\n const nextTableName = resolveTableName(ctor, name, {\n ...existing.config,\n ...config,\n });\n existing.config = {\n ...existing.config,\n ...config,\n tableName: nextTableName,\n };\n if (!existing.schema) {\n existing.schema = {\n ddl: '',\n indexes: [],\n triggers: [],\n tableName: nextTableName,\n columns: {},\n foreignKeys: [],\n dependencies: [],\n version: '',\n };\n }\n existing.schema.tableName = nextTableName;\n existing.constructor = ctor;\n setSmrtTableName(ctor, nextTableName);\n setSmrtQualifiedName(ctor, existing.qualifiedName);\n\n if (existingKey !== nextKey) {\n const classes = getClasses();\n const existingAtNextKey = classes.get(nextKey);\n\n if (existingAtNextKey && existingAtNextKey !== existing) {\n throw new ConfigurationError(\n `Class registry collision while promoting \"${existingKey}\" to \"${nextKey}\". ` +\n 'A different class is already registered under the target key.',\n 'CONFIG_REGISTRY_PROMOTION_COLLISION',\n {\n existingKey,\n nextKey,\n className: name,\n },\n );\n }\n\n classes.delete(existingKey);\n classes.set(nextKey, existing);\n }\n\n getConstructorIndex().set(ctor, nextKey);\n\n // Release C follow-up #1139 Gap 2: we just mutated `existing.name`,\n // `existing.packageName`, `existing.qualifiedName`, `existing.config`,\n // `existing.constructor`, and `existing.schema.tableName`. Any\n // descendant whose cached `inheritedFields` was computed against the\n // prior identity now carries stale data. Invalidate `existing` and\n // every descendant whose `extends` matches the pre- or post-mutation\n // identity so the next field read re-merges from the current state.\n invalidateInheritanceEntries(existing, previousIdentity);\n\n return nextKey;\n }\n\n // Release C (#1134): collision resolution for both exact-match and\n // case-insensitive paths now routes through decideCollisionPolicy, which\n // consolidates the 11-branch if/else tree from pre-C.\n const newSourceFile = getSourceFileFromStack();\n const newPackageName =\n explicitPackageName || getPackageName(ctor, true) || undefined;\n const newInBundledContext = isBundledOutputPath(newSourceFile);\n\n // 1. Exact-match check (existingKey === name)\n if (getClasses().has(name)) {\n const existing = getClasses().get(name);\n if (!existing) {\n throw new Error(\n `Registry inconsistency: ${name} exists in classes Map but get() returned undefined`,\n );\n }\n\n const handled = applyRegisterCollisionPolicy({\n ctor,\n name,\n newPackageName,\n newSourceFile,\n newInBundledContext,\n existing,\n existingKey: name,\n matchKind: 'exact-key',\n upsertExistingEntry,\n });\n if (handled) return;\n }\n\n // 2. Case-insensitive check for manifest stubs (Issue #531, #847) and\n // other same-name-different-case collisions.\n const lowerName = name.toLowerCase();\n for (const [existingKey, existing] of getClasses().entries()) {\n const keyMatches = existingKey.toLowerCase() === lowerName;\n const nameMatches = existing.name?.toLowerCase() === lowerName;\n if (!(keyMatches || nameMatches) || existingKey === name) continue;\n\n const handled = applyRegisterCollisionPolicy({\n ctor,\n name,\n newPackageName,\n newSourceFile,\n newInBundledContext,\n existing,\n existingKey,\n matchKind: 'case-insensitive',\n upsertExistingEntry,\n });\n if (handled) return;\n }\n\n // CRITICAL: Capture package name NOW, while stack trace still shows external package\n // This is called from the @smrt() decorator during import, so the stack trace\n // includes the external package file path. Later calls won't have this context.\n // Skip registry check to avoid circular dependency - class isn't registered yet!\n // This solves issue #159 where external package manifests couldn't be loaded.\n const packageNameFromStack =\n explicitPackageName || getPackageName(ctor, true) || undefined;\n\n // Capture source file path for collision detection during module re-evaluation\n // (Issue #555: Test isolation - class name collision during vitest collection)\n const sourceFilePath = getSourceFileFromStack();\n\n // Get field definitions from manifest\n // Priority order (Issue #270 Phase 1 - synchronous manifest loading):\n // 1. Explicitly provided manifest (_manifest parameter)\n // 2. Test manifests (for test classes)\n // 3. Static manifests (for core framework classes)\n // 4. Cached external manifests (if already loaded)\n // For external packages not yet loaded, manifest discovery happens lazily during schema generation\n // Issue #713: Use lookupInManifest for qualified name support\n let manifestEntry: ReturnType<typeof lookupInManifest> | undefined;\n if (config._manifest) {\n manifestEntry = lookupInManifest(config._manifest, name);\n }\n if (!manifestEntry) {\n manifestEntry = discoverManifestSync(name);\n }\n const fields = new Map<string, RegisteredField>();\n const methods = new Map<string, MethodDefinition>();\n let packageName: string | undefined;\n\n verboseLog(\n `[registry] Registering ${name}: manifestEntry =`,\n manifestEntry ? 'found' : 'not found',\n );\n if (manifestEntry?.fields) {\n verboseLog(\n `[registry] Manifest has ${Object.keys(manifestEntry.fields).length} fields:`,\n Object.keys(manifestEntry.fields),\n );\n }\n\n if (manifestEntry?.fields) {\n // Use manifest fields (from build-time AST scanning)\n // Store field definitions as plain objects with nested options\n for (const [fieldName, fieldDef] of Object.entries(\n manifestEntry.fields,\n ) as [string, FieldDefinition][]) {\n // Build options object, only including defined values\n const options: Record<string, unknown> = { ...fieldDef._meta };\n if (fieldDef.required !== undefined) options.required = fieldDef.required;\n if (fieldDef.default !== undefined) options.default = fieldDef.default;\n if (fieldDef.description !== undefined)\n options.description = fieldDef.description;\n if (fieldDef.transient !== undefined)\n options.transient = fieldDef.transient;\n\n // Store field definition as plain object maintaining Field-like structure\n const field: RegisteredField = {\n type: fieldDef.type,\n };\n\n // Only include options if not empty\n if (Object.keys(options).length > 0) {\n field._meta = options;\n }\n\n // Preserve top-level flags from manifest\n if (fieldDef.transient !== undefined) {\n field.transient = fieldDef.transient;\n }\n if (fieldDef.required !== undefined) {\n field.required = fieldDef.required;\n }\n\n // Hoist related to top level for relationship fields\n // Check both fieldDef.related (new manifests) and _meta.related (old manifests)\n if (fieldDef.related !== undefined) {\n field.related = fieldDef.related;\n } else if (options.related !== undefined) {\n // `related` carries the related class name (always a string at runtime).\n field.related = options.related as string;\n delete field._meta?.related;\n }\n\n fields.set(fieldName, field);\n }\n\n verboseLog(\n `[registry] ✅ Loaded ${fields.size} fields for ${name} from manifest`,\n );\n\n // Use packageName from manifest if available, otherwise from stack trace\n // Priority: explicit manifest > manifestEntry > stack trace\n packageName =\n explicitPackageName ||\n config._manifest?.packageName ||\n manifestEntry.packageName ||\n packageNameFromStack;\n } else {\n // No manifest found yet - use package name from stack trace\n // This will be used later by ensureManifestLoaded() to load the external manifest\n verboseLog(\n `[registry] ⚠️ No manifest entry for ${name} - fields will be loaded later`,\n );\n packageName = packageNameFromStack;\n }\n\n // Apply decorator metadata to override/extend manifest fields\n // Decorators take priority over AST-scanned types (Issue #316)\n const decorators = getFieldDecorators().get(name);\n if (decorators && decorators.size > 0) {\n verboseLog(\n `[registry] Applying ${decorators.size} field decorators for ${name}`,\n );\n\n for (const [fieldName, decoratorOptions] of decorators) {\n // Typed read-view of the raw `Record<string, unknown>` decorator bag so\n // the member reads below narrow to the `RegisteredField` member types\n // they feed (instead of `unknown`). Same runtime object, type-only view.\n const opts: DecoratorFieldOptions = decoratorOptions;\n const existingField = fields.get(fieldName);\n\n if (existingField) {\n // Merge decorator options with manifest field\n // Decorator type takes priority over AST-scanned type\n const mergedMeta: FieldMeta = {\n ...existingField._meta,\n ...decoratorOptions,\n };\n const mergedField: RegisteredField = {\n type: opts.type || existingField.type,\n _meta: mergedMeta,\n };\n\n // Remove 'type' from _meta if it was moved to top level\n if (mergedMeta.type) {\n delete mergedMeta.type;\n }\n\n // Preserve top-level flags (transient, required, etc.)\n if (opts.transient !== undefined) {\n mergedField.transient = opts.transient;\n } else if (existingField.transient !== undefined) {\n mergedField.transient = existingField.transient;\n }\n\n // Handle required flag: nullable fields should not be required\n if (opts.nullable === true) {\n // Nullable explicitly set to true means field is NOT required\n mergedField.required = false;\n mergedMeta.required = false;\n } else if (opts.required !== undefined) {\n mergedField.required = opts.required;\n } else if (existingField.required !== undefined) {\n mergedField.required = existingField.required;\n }\n\n // Hoist related to top level for relationship fields\n if (opts.related !== undefined) {\n mergedField.related = opts.related;\n delete mergedField._meta?.related;\n } else if (existingField.related !== undefined) {\n mergedField.related = existingField.related;\n }\n\n fields.set(fieldName, mergedField);\n verboseLog(\n `[registry] ✅ Merged decorator for ${fieldName}: type=${mergedField.type}`,\n );\n } else {\n // Decorator for field not in manifest - add it\n const newMeta: FieldMeta = decoratorOptions;\n const newField: RegisteredField = {\n type: opts.type || 'text',\n _meta: newMeta,\n };\n\n // Set top-level flags from decorator options\n if (opts.transient !== undefined) {\n newField.transient = opts.transient;\n }\n // Handle required flag: nullable fields should not be required\n if (opts.nullable === true) {\n newField.required = false;\n newMeta.required = false;\n } else if (opts.required !== undefined) {\n newField.required = opts.required;\n }\n\n // Hoist related to top level for relationship fields (Issue #746)\n // This is critical for getRelationshipMap() to detect relationships\n if (opts.related !== undefined) {\n newField.related = opts.related;\n delete newField._meta?.related;\n }\n\n fields.set(fieldName, newField);\n verboseLog(\n `[registry] ✅ Added field ${fieldName} from decorator: type=${opts.type || 'text'}`,\n );\n }\n }\n }\n\n // Handle tenantScoped configuration (Issue #688)\n // External manifests can carry tenantScoped only in decoratorConfig, so\n // registration must honor the merged view rather than only explicit config.\n let tenantScopedConfig: RegisteredClass['tenantScopedConfig'] | undefined;\n const effectiveTenantScoped =\n config.tenantScoped ?? manifestEntry?.decoratorConfig?.tenantScoped;\n if (effectiveTenantScoped) {\n // Normalize boolean or object config into full options\n const tenantOpts =\n typeof effectiveTenantScoped === 'boolean' ? {} : effectiveTenantScoped;\n tenantScopedConfig = {\n mode: tenantOpts.mode ?? 'required',\n field: tenantOpts.field ?? 'tenantId',\n autoFilter: tenantOpts.autoFilter ?? true,\n autoPopulate: tenantOpts.autoPopulate ?? true,\n allowSuperAdminBypass: tenantOpts.allowSuperAdminBypass ?? false,\n };\n\n // Inject or enrich tenantId field\n const fieldName = tenantScopedConfig.field;\n const hadTenantField = fields.has(fieldName);\n ensureTenantScopedField(fields, tenantScopedConfig);\n if (!hadTenantField) {\n verboseLog(\n `[registry] ✅ Injected ${fieldName} field for tenant-scoped class ${name}`,\n );\n }\n }\n\n if (manifestEntry?.methods) {\n // Load method definitions from manifest (for custom CLI/API/MCP generation)\n for (const [methodName, methodDef] of Object.entries(\n manifestEntry.methods,\n )) {\n methods.set(methodName, methodDef);\n }\n }\n\n // Also load methods from _manifestMethods in config (from consumer plugin register.js)\n // This is how external package methods are passed to the registry.\n // `_manifestMethods` is an undeclared escape-hatch carried on the config bag\n // by generated consumer `register.js`, so read it through a narrowed view.\n const manifestMethods = (\n config as unknown as {\n _manifestMethods?: Record<string, MethodDefinition>;\n }\n )._manifestMethods;\n if (manifestMethods) {\n for (const [methodName, methodDef] of Object.entries(manifestMethods)) {\n methods.set(methodName, methodDef);\n }\n verboseLog(\n `[registry] Loaded ${methods.size} methods for ${name} from _manifestMethods`,\n );\n }\n\n // Note: If manifest not found here, it will be loaded asynchronously when needed\n // via ensureManifestLoaded(). This allows decorators to remain synchronous while\n // supporting dynamic external package manifest loading.\n\n // Build inheritance chain from constructor (needed for STI table name resolution)\n const inheritanceChain = buildInheritanceChain(ctor);\n\n // Validate table strategy compatibility with parent (STI requirement)\n if (inheritanceChain.length > 1) {\n // This class has a parent - validate strategy compatibility\n const parentName = inheritanceChain[inheritanceChain.length - 2]; // Second-to-last is parent\n const parentEntry = findClass(parentName);\n\n if (parentEntry) {\n const parentStrategy = parentEntry.config?.tableStrategy || 'default';\n const childStrategy = config.tableStrategy; // Don't default - undefined means inherit\n\n // Only validate if child has an EXPLICIT strategy that differs from parent\n // undefined childStrategy means it will inherit from parent\n if (childStrategy !== undefined && parentStrategy !== childStrategy) {\n throw ConfigurationError.incompatibleStrategy(\n name,\n childStrategy,\n parentName,\n parentStrategy,\n );\n }\n }\n }\n\n // Defer schema generation until needed (generateSchema now uses dynamic import)\n // Store table name for lazy schema generation\n // Priority for STI: manifest's tableName > decorator config > derived from class name\n // The manifest's tableName is computed at build-time when full class hierarchy is known,\n // which correctly handles STI inheritance. The decorator may derive wrong tableName\n // if parent class isn't registered yet at decorator execution time.\n const tableName = resolveTableName(ctor, name, config);\n setSmrtTableName(ctor, tableName);\n\n // Load pre-generated schema from manifest if available, otherwise placeholder\n let schema: SchemaDefinition;\n if (manifestEntry?.schema) {\n // Pre-generated schema from manifest (build-time)\n // Keep indexes as IndexDefinition objects for DDL strategies\n schema = {\n ddl: manifestEntry.schema.ddl,\n indexes:\n manifestEntry.schema.indexes?.map((idx: IndexDefinition) => ({\n name: idx.name,\n columns: idx.columns || [],\n unique: idx.unique || false,\n where: idx.where,\n description: idx.description,\n jsonPath: idx.jsonPath,\n })) || [],\n triggers: [],\n tableName: manifestEntry.schema.tableName || tableName,\n // Cast manifest columns to ColumnDefinition (same shape, TypeScript just needs help)\n columns: cloneManifestSchemaColumns(manifestEntry.schema.columns),\n foreignKeys: [],\n dependencies: [],\n version: manifestEntry.schema.version || '',\n packageName: manifestEntry.packageName,\n };\n verboseLog(\n `[registry] Loaded pre-generated schema for ${name} (${Object.keys(manifestEntry.schema.columns || {}).length} columns)`,\n );\n } else {\n // Placeholder schema - will be generated lazily when first needed\n schema = {\n ddl: '', // Generated lazily\n indexes: [], // Parsed from DDL lazily\n triggers: [], // No longer using database triggers - timestamps managed by application\n tableName,\n columns: {},\n foreignKeys: [],\n dependencies: [],\n version: '',\n packageName: undefined,\n };\n }\n\n if (schema.columns) {\n applySqlTypeOverrides(schema.columns, fields.entries());\n if (decorators && decorators.size > 0) {\n applySqlTypeOverrides(schema.columns, decorators.entries());\n }\n }\n\n // Use pre-computed validation rules from manifest if available (Issue #782)\n // For decorator-based registration, manifest may have pre-computed rules\n const validationRules = manifestEntry?.validationRules;\n let validators: ValidatorFunction[] | undefined;\n\n // Only compile validators if no pre-computed rules exist\n if (!validationRules || validationRules.length === 0) {\n validators = compileValidators(name, fields);\n } else {\n verboseLog(\n `[registry] Using ${validationRules.length} pre-computed validation rules for ${name}`,\n );\n }\n\n // Derive extends from prototype chain if not available from manifest\n // This is critical for inline test classes that use decorators\n let extendsClass: string | undefined = manifestEntry?.extends;\n if (!extendsClass) {\n const proto = Object.getPrototypeOf(ctor);\n if (proto?.name && proto.name !== 'SmrtObject' && proto.name !== 'Object') {\n extendsClass = proto.name;\n }\n }\n\n // Merge manifest's decoratorConfig into config\n // Use the computed tableName which prioritizes manifest's value for STI correctness\n const mergedConfig = {\n ...manifestEntry?.decoratorConfig,\n ...config,\n tableName, // Override with correctly computed tableName\n };\n\n // Generate qualified name if we have a package name\n // Format: \"@package/name:ClassName\"\n const qualifiedName = packageName\n ? createQualifiedName(packageName, name)\n : undefined;\n\n // Determine visibility from config, manifest, or default to 'public'\n // Priority: explicit config > manifest > default\n const visibility: SmrtVisibility =\n config.visibility || manifestEntry?.visibility || 'public';\n\n // Issue #951: Use qualified name as primary key when available\n const registrationKey = qualifiedName || name;\n\n getClasses().set(registrationKey, {\n name,\n qualifiedName, // Qualified name for cross-package identification\n constructor: ctor,\n config: mergedConfig,\n fields,\n methods,\n schema,\n validators,\n validationRules, // Pre-computed rules from manifest (Issue #782)\n tools: manifestEntry?.tools, // AI-callable tool schemas (CLI param schemas)\n // Pluralized endpoint name. Prefer the manifest's computed value (handles\n // STI inheritance + any future inflection changes); fall back to the same\n // simple pluralization the scanner uses for inline/test classes that have\n // no manifest entry. (smrt#1311.)\n collection: manifestEntry?.collection ?? pluralizeCollection(name),\n packageName, // Store package name from manifest for getPackageName() lookup\n sourceFilePath, // Store source file for collision detection (Issue #555)\n extends: extendsClass, // Capture parent class name from manifest OR prototype chain\n extendsTypeArg: manifestEntry?.extendsTypeArg, // SmrtCollection<T> generic arg\n tenantScopedConfig, // Multi-tenancy config (Issue #688)\n visibility, // Visibility control for manifest filtering\n // NOTE: Don't pre-compute inheritanceChain here - let getInheritanceChain() compute\n // it lazily using the `extends` field. This ensures correct chain for both\n // decorator-registered and manifest-loaded classes.\n });\n\n // Release B (#1133): case-insensitive lookups iterate the classes Map\n // directly instead of maintaining a parallel classNameMap index.\n\n // Index constructor for O(1) reverse lookups (Issue #713: constructor-based lookup)\n getConstructorIndex().set(ctor, registrationKey);\n // Stamp the qualified name on the constructor itself as a fallback for\n // runtime code that has a constructor reference but might hit a\n // WeakMap miss (HMR / federated modules / multiple-copy edge cases).\n setSmrtQualifiedName(ctor, qualifiedName);\n\n verboseLog(\n `🎯 Registered smrt object: ${name} (key: ${registrationKey}) with schema for ${schema.tableName} and ${(validators?.length || 0) + (validationRules?.length || 0)} validators/rules`,\n );\n\n // STI sibling auto-loading (Issue #430)\n // When a class is registered that shares a table with other classes (STI),\n // we need to discover and register ALL siblings so that getAllSchemas()\n // can merge columns from all subtypes for the database adapter.\n //\n // IMPORTANT: Only auto-load siblings from EXTERNAL packages.\n // For test classes or classes in the same package, they will be registered\n // by their own @smrt() decorators. Auto-loading them as stubs would cause collisions.\n const collection = manifestEntry?.collection;\n if (collection && !getStiSiblingsLoaded().has(collection)) {\n // Mark this collection as processed to prevent infinite recursion\n getStiSiblingsLoaded().add(collection);\n\n verboseLog(\n `[registry] Checking for STI siblings for collection: ${collection}`,\n );\n\n // Discover all classes that share this collection (table)\n const siblings = discoverSTISiblingsSync(collection);\n\n // Register any siblings that aren't already registered\n // Only load siblings from DIFFERENT packages to avoid collisions with local classes\n for (const sibling of siblings) {\n // Use case-insensitive check to prevent registering 'Praeco' when 'praeco' exists\n if (!hasClassCaseInsensitive(sibling.className)) {\n // Skip siblings from the same package - they will be registered by their own decorators\n if (\n sibling.packageName &&\n packageName &&\n sibling.packageName === packageName\n ) {\n verboseLog(\n `[registry] Skipping STI sibling ${sibling.className} from same package: ${packageName}`,\n );\n continue;\n }\n\n verboseLog(\n `[registry] Auto-loading STI sibling: ${sibling.className} for collection: ${collection}`,\n );\n registerFromManifest(\n sibling.className,\n sibling.entry,\n sibling.packageName,\n );\n }\n }\n }\n}\n\nexport function registerCollection(\n objectName: string,\n // `new (options: any) => SmrtCollection<any>` is the irreducible\n // collection-constructor shape (S4 #1579): the public\n // `ObjectRegistry.registerCollection` wrapper hands a non-generic constructor\n // of exactly this form, which is not assignable to the generic\n // `typeof SmrtCollection`. Mirrors `RegisteredClass.collectionConstructor`.\n collectionConstructor: NonNullable<RegisteredClass['collectionConstructor']>,\n): void {\n const registered = findClass(objectName);\n if (registered) {\n registered.collectionConstructor = collectionConstructor;\n }\n\n // The collections map stores `typeof SmrtCollection`; the runtime value is a\n // SmrtCollection subclass constructor. Bridge the loose constructor shape to\n // the map's element type without `any`.\n getCollections().set(\n objectName,\n collectionConstructor as unknown as Parameters<\n ReturnType<typeof getCollections>['set']\n >[1],\n );\n}\n\n// resolveManifestCollision was removed in Release C (#1134). Its three-branch\n// decision is now represented as explicit rows in the collision-policy\n// decision table — see `manifest-same-source-file`, `manifest-sti-child-wins`,\n// `manifest-sti-parent-skip`, `manifest-default-skip` scenarios in\n// packages/core/src/registry/collision-policy.ts.\n\ntype TenantScopedOptions = Exclude<\n SmartObjectConfig['tenantScoped'],\n boolean | undefined\n>;\n\nfunction normalizeTenantScopedConfig(\n tenantScoped: SmartObjectConfig['tenantScoped'],\n): RegisteredClass['tenantScopedConfig'] | undefined {\n if (!tenantScoped) {\n return undefined;\n }\n\n const tenantOpts: TenantScopedOptions =\n typeof tenantScoped === 'boolean' ? {} : tenantScoped;\n return {\n mode: tenantOpts.mode ?? 'required',\n field: tenantOpts.field ?? 'tenantId',\n autoFilter: tenantOpts.autoFilter ?? true,\n autoPopulate: tenantOpts.autoPopulate ?? true,\n allowSuperAdminBypass: tenantOpts.allowSuperAdminBypass ?? false,\n };\n}\n\nfunction ensureTenantScopedField(\n fields: Map<string, RegisteredField>,\n tenantScopedConfig: RegisteredClass['tenantScopedConfig'] | undefined,\n): void {\n if (!tenantScopedConfig) {\n return;\n }\n\n const fieldName = tenantScopedConfig.field;\n const existingField = fields.get(fieldName);\n if (existingField) {\n fields.set(fieldName, {\n ...existingField,\n required:\n existingField.required ?? tenantScopedConfig.mode === 'required',\n _meta: {\n ...existingField._meta,\n reference: existingField._meta?.reference ?? 'Tenant',\n sqlType: 'UUID',\n __tenancy: {\n ...existingField._meta?.__tenancy,\n isTenantIdField: true,\n ...tenantScopedConfig,\n },\n },\n });\n return;\n }\n\n fields.set(fieldName, {\n type: 'foreignKey',\n related: 'Tenant',\n required: tenantScopedConfig.mode === 'required',\n _meta: {\n reference: 'Tenant',\n sqlType: 'UUID',\n __tenancy: {\n isTenantIdField: true,\n ...tenantScopedConfig,\n },\n },\n });\n}\n\nfunction mergeIndexDefinitions(\n existingIndexes: IndexDefinition[] | undefined,\n manifestIndexes: IndexDefinition[] | undefined,\n): IndexDefinition[] {\n const merged = [...(existingIndexes || [])];\n const seen = new Set(merged.map((index) => index?.name).filter(Boolean));\n\n for (const index of manifestIndexes || []) {\n if (!index?.name || seen.has(index.name)) {\n continue;\n }\n merged.push(index);\n seen.add(index.name);\n }\n\n return merged;\n}\n\n// cloneManifestSchemaColumns lives in ../manifest/store.ts — imported above.\n// (Hoisted out of the duplicate definition here and in registry.ts.)\n\n/**\n * Typed read-view of a raw decorator option bag.\n *\n * `getFieldDecorators()` stores decorator options as\n * `Map<string, Record<string, unknown>>`, so the individual reads come back as\n * `unknown` and won't narrow to the typed `RegisteredField` members they feed.\n * This interface re-types only the members the decorator-merge loop reads, with\n * exactly the target member types, and keeps the open index signature so a raw\n * `Record<string, unknown>` bag is assignable to it without `any`. (The bag's\n * runtime values are field-helper options; this view mirrors that contract.)\n */\ninterface DecoratorFieldOptions {\n type?: FieldDefinition['type'];\n required?: boolean;\n nullable?: boolean;\n transient?: boolean;\n related?: string;\n [key: string]: unknown;\n}\n\n/**\n * Read-only field shape consumed by the SQL-type override helpers.\n *\n * `applySqlTypeOverrides` runs over two sources: the canonical\n * `Map<string, RegisteredField>` AND the raw decorator bag\n * (`Map<string, Record<string, unknown>>` from `getFieldDecorators()`). Both\n * satisfy this shape — every member is optional and the open index signature\n * matches both `RegisteredField`'s index signature and `Record<string, unknown>`\n * — so the helpers read the same overrides off either source without `any`.\n */\ninterface SqlTypeOverrideField {\n type?: unknown;\n sqlType?: unknown;\n __tenancy?: FieldMeta['__tenancy'];\n _meta?: FieldMeta;\n [key: string]: unknown;\n}\n\nfunction getReferenceKindFromFieldOptions(\n fieldOptions: SqlTypeOverrideField,\n): ColumnDefinition['referenceKind'] | undefined {\n if (\n fieldOptions?.__tenancy?.isTenantIdField ||\n fieldOptions?._meta?.__tenancy?.isTenantIdField\n ) {\n return 'tenantId';\n }\n\n if (fieldOptions?.type === 'foreignKey') {\n return 'foreignKey';\n }\n\n if (fieldOptions?.type === 'crossPackageRef') {\n return 'crossPackageRef';\n }\n\n return undefined;\n}\n\nfunction applySqlTypeOverrides(\n columns: Record<string, ColumnDefinition>,\n fieldEntries: Iterable<[string, SqlTypeOverrideField]> | undefined,\n): void {\n if (!fieldEntries) {\n return;\n }\n\n for (const [fieldName, fieldOptions] of fieldEntries) {\n const sqlType = fieldOptions?.sqlType ?? fieldOptions?._meta?.sqlType;\n const referenceKind = getReferenceKindFromFieldOptions(fieldOptions);\n if (!sqlType && !referenceKind) {\n continue;\n }\n\n const columnName = toSnakeCase(fieldName);\n const existingColumn = columns[columnName];\n if (!existingColumn) {\n continue;\n }\n\n columns[columnName] = {\n ...existingColumn,\n ...(sqlType\n ? { type: String(sqlType).toUpperCase() as ColumnDefinition['type'] }\n : {}),\n ...(referenceKind ? { referenceKind } : {}),\n };\n }\n}\n\n/**\n * Invalidate cached inheritance state (chain + inheritedFields +\n * inheritedMethods) on `existing` AND every descendant whose `extends` or\n * `inheritanceChain` references it.\n *\n * This covers both simple-name and qualified-name `extends` matches, which\n * is why `ObjectRegistry.invalidateInheritanceCache` delegates here (Release\n * C follow-up #1139 Gap 1 — the old recursive public helper only matched\n * `extends === className` by exact string, silently missing qualified\n * descendants like `@pkg:Parent`).\n *\n * `previousIdentity` is used by `upsertExistingEntry` (Gap 2): when a class\n * is promoted (its name/packageName/qualifiedName are mutated in place),\n * descendants registered against the pre-mutation identity need to be\n * invalidated too. Pass the pre-mutation `{ name, qualifiedName }` so this\n * sweep matches against both the old and new identity.\n *\n * Exported for the public `ObjectRegistry.invalidateInheritanceCache`\n * shim in registry.ts.\n */\nexport function invalidateInheritanceEntries(\n existing: RegisteredClass,\n previousIdentity?: {\n name?: string;\n qualifiedName?: string;\n },\n): void {\n const cache = getInheritanceCache();\n const affectedNames = new Set<string>();\n\n const remember = (name: string | undefined): void => {\n if (name) {\n affectedNames.add(name);\n }\n };\n\n const matchNames = new Set<string>();\n const rememberMatch = (name: string | undefined): void => {\n if (name) matchNames.add(name);\n };\n rememberMatch(existing.name);\n rememberMatch(existing.qualifiedName);\n rememberMatch(previousIdentity?.name);\n rememberMatch(previousIdentity?.qualifiedName);\n\n for (const name of matchNames) {\n remember(name);\n }\n\n for (const [key, candidate] of getClasses()) {\n const extendsMatches =\n !!candidate.extends && matchNames.has(candidate.extends);\n const chainMatches =\n !!candidate.inheritanceChain &&\n candidate.inheritanceChain.some((n) => matchNames.has(n));\n\n if (candidate === existing || extendsMatches || chainMatches) {\n candidate.inheritanceChain = undefined;\n candidate.inheritedFields = undefined;\n candidate.inheritedMethods = undefined;\n remember(key);\n remember(candidate.name);\n remember(candidate.qualifiedName);\n }\n }\n\n for (const name of affectedNames) {\n cache.delete(name);\n }\n}\n\nfunction mergeManifestIntoExistingRegistration(\n existing: RegisteredClass,\n objectDef: SmartObjectDefinition,\n packageName?: string,\n): void {\n const manifestConfig = objectDef.decoratorConfig || {};\n const manifestTableName =\n objectDef.schema?.tableName ||\n manifestConfig.tableName ||\n existing.schema?.tableName ||\n existing.config.tableName ||\n tableNameFromClass(existing.constructor);\n\n existing.config = {\n ...manifestConfig,\n ...existing.config,\n tableName: manifestTableName,\n };\n\n if (objectDef.fields) {\n for (const [fieldName, fd] of Object.entries(objectDef.fields)) {\n if (!existing.fields.has(fieldName)) {\n existing.fields.set(fieldName, createFieldFromManifest(fd));\n continue;\n }\n\n const existingField = existing.fields.get(fieldName);\n if (!existingField) {\n continue;\n }\n\n existing.fields.set(fieldName, mergeManifestField(existingField, fd));\n }\n }\n\n const tenantScopedConfig = normalizeTenantScopedConfig(\n existing.config.tenantScoped,\n );\n if (tenantScopedConfig) {\n existing.tenantScopedConfig = tenantScopedConfig;\n ensureTenantScopedField(existing.fields, tenantScopedConfig);\n }\n\n if (objectDef.methods) {\n for (const [methodName, methodDef] of Object.entries(objectDef.methods)) {\n existing.methods.set(methodName, methodDef);\n }\n }\n\n if (objectDef.schema) {\n const manifestSchema: SchemaDefinition = {\n ddl: objectDef.schema.ddl || '',\n indexes:\n objectDef.schema.indexes?.map((idx: IndexDefinition) => ({\n name: idx.name,\n columns: idx.columns || [],\n unique: idx.unique || false,\n where: idx.where,\n description: idx.description,\n jsonPath: idx.jsonPath,\n })) || [],\n triggers: [],\n tableName: objectDef.schema.tableName || manifestTableName,\n columns: cloneManifestSchemaColumns(objectDef.schema.columns),\n foreignKeys: [],\n dependencies: [],\n version: objectDef.schema.version || '',\n packageName: packageName,\n };\n\n applySqlTypeOverrides(manifestSchema.columns, existing.fields.entries());\n\n existing.schema = {\n ...(existing.schema || {}),\n ...manifestSchema,\n tableName: manifestSchema.tableName,\n ddl: manifestSchema.ddl || existing.schema?.ddl || '',\n columns: {\n ...(existing.schema?.columns || {}),\n ...(manifestSchema.columns || {}),\n },\n indexes: mergeIndexDefinitions(\n existing.schema?.indexes,\n manifestSchema.indexes,\n ),\n packageName: packageName || existing.schema?.packageName,\n };\n } else if (!existing.schema) {\n existing.schema = {\n ddl: '',\n indexes: [],\n triggers: [],\n tableName: manifestTableName,\n columns: {},\n foreignKeys: [],\n dependencies: [],\n version: '',\n packageName: packageName,\n };\n } else {\n existing.schema.tableName = manifestTableName;\n existing.schema.packageName = packageName || existing.schema.packageName;\n }\n\n if (objectDef.validationRules !== undefined) {\n existing.validationRules = objectDef.validationRules;\n existing.validators = undefined;\n } else if (!existing.validationRules && !existing.validators) {\n existing.validators = compileValidators(existing.name, existing.fields);\n }\n\n if (packageName) {\n existing.packageName = packageName;\n existing.qualifiedName = createQualifiedName(\n packageName,\n existing.name,\n ) as QualifiedClassName;\n } else if (!existing.packageName && objectDef.packageName) {\n existing.packageName = objectDef.packageName;\n }\n\n if (objectDef.extends) {\n existing.extends = packageName\n ? qualifyExtendsName(objectDef.extends, packageName)\n : objectDef.extends;\n }\n\n if (!existing.sourceFilePath && objectDef.filePath) {\n existing.sourceFilePath = objectDef.filePath;\n }\n\n existing.visibility =\n objectDef.visibility || manifestConfig.visibility || existing.visibility;\n invalidateInheritanceEntries(existing);\n}\n\nexport function registerFromManifest(\n name: string,\n objectDef: SmartObjectDefinition,\n packageName?: string,\n): void {\n // Issue #951: Compute simple class name and registration key early\n // `name` may be a qualified key from manifest (e.g., '@happyvertical/smrt-events:Event')\n // `simpleClassName` is always the plain class name (e.g., 'Event')\n const simpleClassName = objectDef.className || name;\n const qualifiedNameEarly = packageName\n ? createQualifiedName(packageName, simpleClassName)\n : objectDef.qualifiedName;\n const registrationKey = (qualifiedNameEarly || name) as string;\n\n // Release C (#1134): collision resolution routes through\n // decideCollisionPolicy. See collision-policy.ts for the 16-row decision\n // table; applyManifestCollisionPolicy below turns a policy into registry\n // mutations.\n //\n // Two collision checks, matching pre-C behavior:\n // 1. Canonical-name lookup (case-insensitive simple-name match; covers\n // issue #950's STI child-wins and issue #951's qualified coexistence).\n // 2. Exact-key match (handles re-registration with same qualified key).\n //\n // The ambiguous case (multiple existing entries share the simple name —\n // `getCanonicalClassName` returns undefined) is NOT fed through the table.\n // It falls through both checks into the new-registration code below,\n // preserving issue #951's coexistence semantics.\n const existingCanonical = getCanonicalClassName(simpleClassName);\n if (existingCanonical) {\n const existing = getClasses().get(existingCanonical);\n if (existing) {\n const outcome = applyManifestCollisionPolicy({\n name,\n objectDef,\n packageName,\n existing,\n existingKey: existingCanonical,\n registrationKey,\n matchKind: 'canonical-name',\n });\n if (outcome === 'return') return;\n // outcome === 'continue' means policy was replace (child-wins) or\n // coexist — fall through into the new-registration code below.\n }\n // else: stale map entry (key exists but class was removed) — allow registration\n }\n\n if (getClasses().has(registrationKey)) {\n const existing = getClasses().get(registrationKey);\n if (!existing) return;\n const outcome = applyManifestCollisionPolicy({\n name,\n objectDef,\n packageName,\n existing,\n existingKey: registrationKey,\n registrationKey,\n matchKind: 'exact-key',\n });\n if (outcome === 'return') return;\n }\n\n // Issue #1004: Qualify the `extends` value BEFORE inserting this class\n // into the classes Map. Otherwise qualifyExtendsName would iterate and\n // find the child's own entry, creating a circular extends chain\n // (e.g., @test/sports:TestEvent extends itself). Release B (#1133) swapped\n // the underlying classNameMap lookup for an iteration over `classes`, but\n // the ordering invariant still holds.\n const qualifiedExtends =\n objectDef.extends && packageName\n ? qualifyExtendsName(objectDef.extends, packageName)\n : objectDef.extends;\n\n // Release B (#1133): case-insensitive lookups iterate the classes Map\n // directly; no parallel classNameMap index to maintain.\n\n // Create stub constructor - not needed for CLI command generation\n // The CLI only needs metadata (fields, methods, config)\n // Mark as manifest stub so real class can replace it during decorator registration\n const stubConstructor = class extends SmrtObject {\n static readonly _isManifestStub = true;\n } as typeof SmrtObject;\n Object.defineProperty(stubConstructor, 'name', { value: simpleClassName });\n\n // Convert manifest field definitions to Field objects\n const fields = new Map<string, RegisteredField>();\n const decorators = getFieldDecorators().get(simpleClassName);\n if (objectDef.fields) {\n for (const [fieldName, fd] of Object.entries(objectDef.fields)) {\n fields.set(fieldName, createFieldFromManifest(fd));\n }\n }\n\n // Load method definitions\n const methods = new Map<string, MethodDefinition>();\n if (objectDef.methods) {\n for (const [methodName, methodDef] of Object.entries(objectDef.methods)) {\n methods.set(methodName, methodDef);\n }\n }\n\n // Get config from manifest\n const config = objectDef.decoratorConfig || {};\n const tableName = config.tableName || tableNameFromClass(stubConstructor);\n\n // Load pre-generated schema from manifest if available\n // This enables efficient external package consumption without runtime schema generation\n let schema: SchemaDefinition;\n if (objectDef.schema) {\n // Pre-generated schema from manifest (build-time)\n // Keep indexes as IndexDefinition objects for DDL strategies\n schema = {\n ddl: objectDef.schema.ddl,\n indexes:\n objectDef.schema.indexes?.map((idx: IndexDefinition) => ({\n name: idx.name,\n columns: idx.columns || [],\n unique: idx.unique || false,\n where: idx.where,\n description: idx.description,\n jsonPath: idx.jsonPath,\n })) || [],\n triggers: [],\n tableName: objectDef.schema.tableName,\n columns: cloneManifestSchemaColumns(objectDef.schema.columns),\n foreignKeys: [],\n dependencies: [],\n version: objectDef.schema.version || '',\n packageName: packageName,\n };\n applySqlTypeOverrides(schema.columns, fields.entries());\n applySqlTypeOverrides(schema.columns, decorators?.entries());\n verboseLog(\n `[registry] Loaded pre-generated schema for ${name} (${Object.keys(objectDef.schema.columns || {}).length} columns)`,\n );\n } else {\n // Placeholder schema - will be generated at runtime if needed\n schema = {\n ddl: '',\n indexes: [],\n triggers: [],\n tableName,\n columns: {},\n foreignKeys: [],\n dependencies: [],\n version: '',\n packageName: packageName,\n };\n }\n\n // Use pre-computed validation rules from manifest if available (Issue #782)\n // This avoids compiling validator closures at runtime, reducing startup time\n const validationRules = objectDef.validationRules;\n let validators: ValidatorFunction[] | undefined;\n\n // Only compile validators if no pre-computed rules exist\n // (backward compatibility for older manifests)\n if (!validationRules || validationRules.length === 0) {\n validators = compileValidators(name, fields);\n verboseLog(\n `[registry] No pre-computed rules for ${name}, compiled ${validators.length} validators`,\n );\n } else {\n verboseLog(\n `[registry] Using ${validationRules.length} pre-computed validation rules for ${name}`,\n );\n }\n\n // Issue #951: Use qualifiedNameEarly computed at the top of this function\n // (uses simpleClassName, not the manifest key which may already be qualified)\n const qualifiedName = qualifiedNameEarly;\n\n // Get visibility from manifest (defaults to 'public')\n const visibility: SmrtVisibility =\n objectDef.visibility || config.visibility || 'public';\n\n // Register in ObjectRegistry (metadata only, no collection constructor)\n // Manifest registration is for command discovery and help text.\n // Runtime execution requires real classes loaded from entry point.\n //\n // Issue #847: Use className from objectDef (simple name like 'Council') for the name\n // property, not the qualified name key. This enables getFields() lookups by simple\n // class name to work correctly. simpleClassName is defined earlier in this function.\n //\n // Issue #951: Use registrationKey (qualified when available) as the primary key\n getClasses().set(registrationKey, {\n name: simpleClassName,\n qualifiedName, // Qualified name for cross-package identification\n constructor: stubConstructor,\n config,\n fields,\n methods,\n schema,\n validators,\n validationRules, // Pre-computed rules from manifest (Issue #782)\n tools: objectDef.tools, // AI-callable tool schemas (used for CLI param schemas)\n // Pluralized endpoint name; fall back to simple pluralization if a\n // (legacy) manifest lacks it. (smrt#1311.)\n collection: objectDef.collection ?? pluralizeCollection(simpleClassName),\n packageName,\n sourceFilePath: objectDef.filePath, // Store source file for collision detection (Issue #555)\n extends: qualifiedExtends, // Issue #1004: Pre-computed qualified parent\n extendsTypeArg: objectDef.extendsTypeArg, // SmrtCollection<T> generic arg\n visibility, // New: Visibility control for manifest filtering\n });\n // Tag the synthetic stub constructor with the qualified name so the\n // same constructor-side identity convention holds for manifest-loaded\n // classes as well as decorator-registered ones.\n setSmrtQualifiedName(stubConstructor, qualifiedName);\n\n verboseLog(\n `📦 Registered ${simpleClassName} from manifest (key: ${registrationKey}, ${fields.size} fields, ${methods.size} methods)`,\n );\n\n // STI sibling auto-loading (Issue #430)\n // When a class is registered that shares a table with other classes (STI),\n // we need to discover and register ALL siblings so that getAllSchemas()\n // can merge columns from all subtypes for the database adapter.\n //\n // IMPORTANT: Only auto-load siblings from EXTERNAL packages.\n // For test classes or classes in the same package, they will be registered\n // by their own @smrt() decorators. Auto-loading them as stubs would cause collisions.\n const collection = objectDef.collection;\n if (collection && !getStiSiblingsLoaded().has(collection)) {\n // Mark this collection as processed to prevent infinite recursion\n getStiSiblingsLoaded().add(collection);\n\n verboseLog(\n `[registry] Checking for STI siblings for collection: ${collection}`,\n );\n\n // Discover all classes that share this collection (table)\n const siblings = discoverSTISiblingsSync(collection);\n\n // Register any siblings that aren't already registered\n // Only load siblings from DIFFERENT packages to avoid collisions with local classes\n for (const sibling of siblings) {\n // Use case-insensitive check to prevent registering 'Praeco' when 'praeco' exists\n if (!hasClassCaseInsensitive(sibling.className)) {\n // Skip siblings from the same package - they will be registered by their own decorators\n if (\n sibling.packageName &&\n packageName &&\n sibling.packageName === packageName\n ) {\n verboseLog(\n `[registry] Skipping STI sibling ${sibling.className} from same package: ${packageName}`,\n );\n continue;\n }\n\n verboseLog(\n `[registry] Auto-loading STI sibling: ${sibling.className} for collection: ${collection}`,\n );\n registerFromManifest(\n sibling.className,\n sibling.entry,\n sibling.packageName,\n );\n }\n }\n }\n}\n"],"names":[],"mappings":"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"}