@happyvertical/smrt-core 0.53.1 → 0.53.3

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 (70) hide show
  1. package/AGENTS.md +4 -0
  2. package/README.md +49 -0
  3. package/agents/test-types.md +29 -0
  4. package/dist/decorators/index.d.ts +8 -0
  5. package/dist/decorators/index.d.ts.map +1 -1
  6. package/dist/decorators/index.js.map +1 -1
  7. package/dist/generators/mcp.js.map +1 -1
  8. package/dist/index.d.ts +1 -0
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/manifest/static-manifest.d.ts.map +1 -1
  11. package/dist/manifest/static-manifest.js +4 -3
  12. package/dist/manifest/static-manifest.js.map +1 -1
  13. package/dist/manifest/store.js +1 -1
  14. package/dist/manifest/store.js.map +1 -1
  15. package/dist/manifest.json +4 -3
  16. package/dist/object.d.ts +3 -1
  17. package/dist/object.d.ts.map +1 -1
  18. package/dist/object.js +2 -0
  19. package/dist/object.js.map +1 -1
  20. package/dist/registry/class-registration.d.ts.map +1 -1
  21. package/dist/registry/class-registration.js +72 -9
  22. package/dist/registry/class-registration.js.map +1 -1
  23. package/dist/registry/runtime-overrides.d.ts +34 -0
  24. package/dist/registry/runtime-overrides.d.ts.map +1 -0
  25. package/dist/registry/runtime-overrides.js +78 -0
  26. package/dist/registry/runtime-overrides.js.map +1 -0
  27. package/dist/registry/schema-builder.d.ts.map +1 -1
  28. package/dist/registry/schema-builder.js +3 -3
  29. package/dist/registry/schema-builder.js.map +1 -1
  30. package/dist/registry/subtype-lineage.d.ts +10 -0
  31. package/dist/registry/subtype-lineage.d.ts.map +1 -0
  32. package/dist/registry/subtype-lineage.js +57 -0
  33. package/dist/registry/subtype-lineage.js.map +1 -0
  34. package/dist/registry/types.d.ts +2 -0
  35. package/dist/registry/types.d.ts.map +1 -1
  36. package/dist/registry.d.ts +13 -1
  37. package/dist/registry.d.ts.map +1 -1
  38. package/dist/registry.js +17 -0
  39. package/dist/registry.js.map +1 -1
  40. package/dist/scanner/manifest-generator.d.ts.map +1 -1
  41. package/dist/scanner/manifest-generator.js +2 -2
  42. package/dist/scanner/manifest-generator.js.map +1 -1
  43. package/dist/scanner/types.d.ts +2 -0
  44. package/dist/scanner/types.d.ts.map +1 -1
  45. package/dist/scanner/types.js.map +1 -1
  46. package/dist/schema/foreign-key-policy.d.ts +2 -0
  47. package/dist/schema/foreign-key-policy.d.ts.map +1 -1
  48. package/dist/schema/foreign-key-policy.js +5 -1
  49. package/dist/schema/foreign-key-policy.js.map +1 -1
  50. package/dist/schema/generator.d.ts.map +1 -1
  51. package/dist/schema/generator.js +4 -4
  52. package/dist/schema/generator.js.map +1 -1
  53. package/dist/smrt-knowledge.json +13 -7
  54. package/package.json +5 -5
  55. package/dist/__tests__/fixtures/collection-coverage-fixtures.d.ts +0 -20
  56. package/dist/__tests__/fixtures/collection-coverage-fixtures.d.ts.map +0 -1
  57. package/dist/__tests__/fixtures/inheritance-resolver-fixtures.d.ts +0 -37
  58. package/dist/__tests__/fixtures/inheritance-resolver-fixtures.d.ts.map +0 -1
  59. package/dist/__tests__/fixtures/inheritance-test-classes.d.ts +0 -48
  60. package/dist/__tests__/fixtures/inheritance-test-classes.d.ts.map +0 -1
  61. package/dist/__tests__/fixtures/mcp-integration-test-classes.d.ts +0 -18
  62. package/dist/__tests__/fixtures/mcp-integration-test-classes.d.ts.map +0 -1
  63. package/dist/__tests__/fixtures/object-ai-memory-fixtures.d.ts +0 -25
  64. package/dist/__tests__/fixtures/object-ai-memory-fixtures.d.ts.map +0 -1
  65. package/dist/__tests__/fixtures/object-spec-test-classes.d.ts +0 -13
  66. package/dist/__tests__/fixtures/object-spec-test-classes.d.ts.map +0 -1
  67. package/dist/__tests__/fixtures/registry-test-classes.d.ts +0 -23
  68. package/dist/__tests__/fixtures/registry-test-classes.d.ts.map +0 -1
  69. package/dist/registry/__tests__/helpers/consumer-workspace.d.ts +0 -42
  70. package/dist/registry/__tests__/helpers/consumer-workspace.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"class-registration.d.ts","sourceRoot":"","sources":["../../src/registry/class-registration.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAuBH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,KAAK,EAKV,qBAAqB,EAGtB,MAAM,qBAAqB,CAAC;AA4C7B,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EACf,iBAAiB,EAElB,MAAM,YAAY,CAAC;AAkDpB;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAS3E;AA4BD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,OAAO,CAeT;AA4nBD;;;;GAIG;AACH,wBAAgB,QAAQ,CACtB,IAAI,EAAE,OAAO,UAAU,EACvB,MAAM,GAAE,iBAAsB,GAC7B,IAAI,CAON;AAmiCD,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,EAMlB,qBAAqB,EAAE,WAAW,CAAC,eAAe,CAAC,uBAAuB,CAAC,CAAC,GAC3E,IAAI,CAeN;AA+BD,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,EACpC,kBAAkB,EAAE,eAAe,CAAC,oBAAoB,CAAC,GAAG,SAAS,GACpE,IAAI,CAyCN;AAoHD;;;;;;;;;;;;;;;;;;;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,CA4CN;AAkLD,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,qBAAqB,EAChC,mBAAmB,CAAC,EAAE,MAAM,GAC3B,IAAI,CAQN"}
1
+ {"version":3,"file":"class-registration.d.ts","sourceRoot":"","sources":["../../src/registry/class-registration.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAuBH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,KAAK,EAKV,qBAAqB,EAGtB,MAAM,qBAAqB,CAAC;AAqD7B,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EACf,iBAAiB,EAElB,MAAM,YAAY,CAAC;AAkDpB;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAS3E;AA4BD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,OAAO,CAeT;AA2oBD;;;;GAIG;AACH,wBAAgB,QAAQ,CACtB,IAAI,EAAE,OAAO,UAAU,EACvB,MAAM,GAAE,iBAAsB,GAC7B,IAAI,CASN;AAomCD,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,EAMlB,qBAAqB,EAAE,WAAW,CAAC,eAAe,CAAC,uBAAuB,CAAC,CAAC,GAC3E,IAAI,CAeN;AA+BD,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,EACpC,kBAAkB,EAAE,eAAe,CAAC,oBAAoB,CAAC,GAAG,SAAS,GACpE,IAAI,CAyCN;AAoHD;;;;;;;;;;;;;;;;;;;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,CA4CN;AAmLD,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,qBAAqB,EAChC,mBAAmB,CAAC,EAAE,MAAM,GAC3B,IAAI,CAUN"}
@@ -15,6 +15,8 @@ import { SmrtObject } from "../object.js";
15
15
  import { decideCollisionPolicy } from "./collision-policy.js";
16
16
  import { isFrameworkBaseClass } from "./framework-base-classes.js";
17
17
  import { createFieldFromManifest, mergeManifestField } from "./manifest-field-merge.js";
18
+ import { applyRuntimeOverrides, transferRuntimeOverride } from "./runtime-overrides.js";
19
+ import { isSubtypeOf, reconcileSubtypeLineage, recordSubtypeParent } from "./subtype-lineage.js";
18
20
  //#region src/registry/class-registration.ts
19
21
  /**
20
22
  * Class registration module for the SMRT ObjectRegistry.
@@ -240,9 +242,10 @@ function applyRegisterCollisionPolicy(args) {
240
242
  function buildManifestCollisionInputs(args) {
241
243
  const { name, objectDef, packageName, existing, existingKey, registrationKey, matchKind } = args;
242
244
  const newClassName = objectDef.className || name;
243
- const newExtends = objectDef.extends;
244
- const newExtendsExisting = !!(newExtends && (newExtends === existing.name || newExtends === existingKey || newExtends.toLowerCase() === existing.name.toLowerCase()));
245
- const existingExtendsNew = !!(existing.extends && (existing.extends === newClassName || existing.extends === name || existing.extends === registrationKey || existing.extends.toLowerCase() === newClassName.toLowerCase()));
245
+ const newExtends = objectDef.extendsQualified ?? objectDef.extends;
246
+ const knownAncestor = existing.replacedQualifiedNames?.includes(registrationKey) === true || isSubtypeOf(existingKey, registrationKey);
247
+ const newExtendsExisting = !knownAncestor && (isSubtypeOf(registrationKey, existingKey) || !!(newExtends && (newExtends === existing.name || newExtends === existingKey || newExtends.toLowerCase() === existing.name.toLowerCase())));
248
+ const existingExtendsNew = knownAncestor || !newExtendsExisting && !!(existing.extends && (existing.extends === newClassName || existing.extends === name || existing.extends === registrationKey || existing.extends.toLowerCase() === newClassName.toLowerCase()));
246
249
  const newSourceFile = objectDef.filePath;
247
250
  const bothSourceFilesKnown = !!(newSourceFile && existing.sourceFilePath);
248
251
  const sameSourceFile = bothSourceFilesKnown && newSourceFile === existing.sourceFilePath;
@@ -290,6 +293,9 @@ function applyManifestCollisionPolicy(args) {
290
293
  verboseLog(`[registry] ${decision.scenario}: skipping manifest '${args.name}' (${decision.reason})`);
291
294
  return "return";
292
295
  case "replace":
296
+ args.replacedQualifiedNames.add(args.existingKey);
297
+ for (const ancestor of args.existing.replacedQualifiedNames ?? []) args.replacedQualifiedNames.add(ancestor);
298
+ transferRuntimeOverride(args.existingKey, args.registrationKey);
293
299
  getClasses().delete(args.existingKey);
294
300
  verboseLog(`[registry] ${decision.scenario}: '${args.name}' replaces '${args.existingKey}' (${decision.reason})`);
295
301
  return "continue";
@@ -425,6 +431,8 @@ function register(ctor, config = {}) {
425
431
  try {
426
432
  registerUntracked(ctor, config);
427
433
  } finally {
434
+ reconcileSubtypeLineage();
435
+ applyRuntimeOverrides();
428
436
  bumpRegistryGeneration();
429
437
  }
430
438
  }
@@ -433,6 +441,8 @@ function registerUntracked(ctor, config = {}) {
433
441
  const explicitPackageName = config.packageName;
434
442
  let promotedCollectionConstructor;
435
443
  let promotedRuntimeConfig;
444
+ let promotedReplacementAncestry;
445
+ let isolatedSubtypeParent;
436
446
  let isolatedManifestEntry;
437
447
  if (config._manifestKey) {
438
448
  if (!explicitPackageName || !config._manifest) throw new ConfigurationError("Generated isolated manifest registration requires packageName and _manifest.", "CONFIG_INVALID_ISOLATED_MANIFEST");
@@ -484,6 +494,14 @@ function registerUntracked(ctor, config = {}) {
484
494
  };
485
495
  existing.schema.tableName = nextTableName;
486
496
  if (existing.constructor._isManifestStub === true && newSourceFile) existing.sourceFilePath = newSourceFile;
497
+ if (ctor !== existing.constructor && ctor.prototype instanceof existing.constructor) {
498
+ existing.replacedQualifiedNames = [.../* @__PURE__ */ new Set([...existing.replacedQualifiedNames ?? [], existingKey])];
499
+ const ownTenancy = normalizeTenantScopedConfig(config.tenantScoped);
500
+ if (ownTenancy) {
501
+ existing.tenantScopedConfig = ownTenancy;
502
+ existing.tenantScopedConfigSource = "explicit";
503
+ }
504
+ }
487
505
  existing.constructor = ctor;
488
506
  setSmrtTableName(ctor, nextTableName);
489
507
  declareSensitiveTable(existing.config, nextTableName, existing.schema?.tableName);
@@ -496,6 +514,7 @@ function registerUntracked(ctor, config = {}) {
496
514
  nextKey,
497
515
  className: name
498
516
  });
517
+ transferRuntimeOverride(existingKey, nextKey);
499
518
  classes.delete(existingKey);
500
519
  classes.set(nextKey, existing);
501
520
  }
@@ -519,6 +538,7 @@ function registerUntracked(ctor, config = {}) {
519
538
  });
520
539
  promotedCollectionConstructor = constructorEntry.collectionConstructor || targetCollectionConstructor;
521
540
  promotedRuntimeConfig = constructorEntry.config;
541
+ promotedReplacementAncestry = constructorEntry.replacedQualifiedNames;
522
542
  getClasses().delete(constructorKey);
523
543
  getConstructorIndex().delete(ctor);
524
544
  if (targetIsManifestStub && targetEntry) {
@@ -536,8 +556,25 @@ function registerUntracked(ctor, config = {}) {
536
556
  const ownQualifiedKey = newPackageName ? createQualifiedName(newPackageName, name) : void 0;
537
557
  const ownPackageDeclaresClass = !!ownQualifiedKey && (!!explicitPackageName || stackPackageDeclaresClass || !!sourceManifestPackage);
538
558
  const belongsToAnotherPackage = (existing) => ownPackageDeclaresClass && !!existing.packageName && existing.packageName !== newPackageName;
559
+ for (const [key, existing] of getClasses()) {
560
+ if (existing.name !== name || ctor === existing.constructor) continue;
561
+ if (resolveTableName(ctor, name, {
562
+ ...config,
563
+ ...newPackageName ? { packageName: newPackageName } : {}
564
+ }) !== existing.schema?.tableName) continue;
565
+ if (ctor.prototype instanceof existing.constructor) {
566
+ if (isolatedManifestEntry) {
567
+ isolatedSubtypeParent = [key, existing];
568
+ promotedCollectionConstructor ??= existing.collectionConstructor;
569
+ break;
570
+ }
571
+ upsertExistingEntry(key, existing);
572
+ return;
573
+ }
574
+ if (existing.constructor.prototype instanceof ctor) return;
575
+ }
539
576
  const exactExisting = getClasses().get(name);
540
- if (exactExisting && !belongsToAnotherPackage(exactExisting)) {
577
+ if (exactExisting && exactExisting !== isolatedSubtypeParent?.[1] && !belongsToAnotherPackage(exactExisting)) {
541
578
  const existing = exactExisting;
542
579
  if (applyRegisterCollisionPolicy({
543
580
  ctor,
@@ -554,6 +591,7 @@ function registerUntracked(ctor, config = {}) {
554
591
  }
555
592
  const lowerName = name.toLowerCase();
556
593
  for (const [existingKey, existing] of getClasses().entries()) {
594
+ if (existing === isolatedSubtypeParent?.[1]) continue;
557
595
  const keyMatches = existingKey.toLowerCase() === lowerName;
558
596
  const nameMatches = existing.name?.toLowerCase() === lowerName;
559
597
  if (!(keyMatches || nameMatches) || existingKey === name) continue;
@@ -763,7 +801,7 @@ function registerUntracked(ctor, config = {}) {
763
801
  let validators;
764
802
  if (validationRules === void 0) validators = compileValidators(name, fields);
765
803
  else verboseLog(`[registry] Using ${validationRules.length} pre-computed validation rules for ${name}`);
766
- let extendsClass = manifestEntry?.extends;
804
+ let extendsClass = manifestEntry?.extendsQualified ?? manifestEntry?.extends;
767
805
  if (!extendsClass) {
768
806
  const proto = Object.getPrototypeOf(ctor);
769
807
  if (proto?.name && proto.name !== "SmrtObject" && proto.name !== "Object") extendsClass = proto.name;
@@ -792,6 +830,7 @@ function registerUntracked(ctor, config = {}) {
792
830
  tools: manifestEntry?.tools,
793
831
  collection: manifestEntry?.collection ?? inheritedStiCollection(ctor) ?? pluralizeCollection(name),
794
832
  collectionConstructor: promotedCollectionConstructor,
833
+ replacedQualifiedNames: promotedReplacementAncestry,
795
834
  packageName,
796
835
  sourceFilePath,
797
836
  extends: extendsClass,
@@ -801,6 +840,21 @@ function registerUntracked(ctor, config = {}) {
801
840
  visibility
802
841
  };
803
842
  assertQualifiedNameAliasesAvailable(registrationKey, registration);
843
+ if (isolatedSubtypeParent) {
844
+ const [parentKey, parent] = isolatedSubtypeParent;
845
+ registration.replacedQualifiedNames = [.../* @__PURE__ */ new Set([
846
+ ...registration.replacedQualifiedNames ?? [],
847
+ parentKey,
848
+ ...parent.replacedQualifiedNames ?? []
849
+ ])];
850
+ if (parentKey === registrationKey) registration.extends = parent.extends;
851
+ transferRuntimeOverride(parentKey, registrationKey);
852
+ getClasses().delete(parentKey);
853
+ invalidateInheritanceEntries(registration, {
854
+ name: parent.name,
855
+ qualifiedName: parent.qualifiedName
856
+ });
857
+ }
804
858
  getClasses().set(registrationKey, registration);
805
859
  getConstructorIndex().set(ctor, registrationKey);
806
860
  setSmrtQualifiedName(ctor, qualifiedName);
@@ -1057,7 +1111,8 @@ function mergeManifestIntoExistingRegistration(existing, objectDef, packageName)
1057
1111
  existing.packageName = packageName;
1058
1112
  existing.qualifiedName = createQualifiedName(packageName, existing.name);
1059
1113
  } else if (!existing.packageName && objectDef.packageName) existing.packageName = objectDef.packageName;
1060
- if (objectDef.extends) existing.extends = packageName ? qualifyExtendsName(objectDef.extends, packageName) : objectDef.extends;
1114
+ const manifestParent = objectDef.extendsQualified ?? objectDef.extends;
1115
+ if (manifestParent) existing.extends = packageName ? qualifyExtendsName(manifestParent, packageName) : manifestParent;
1061
1116
  if (!existing.sourceFilePath && objectDef.filePath) existing.sourceFilePath = objectDef.filePath;
1062
1117
  if (objectDef.collection) existing.collection = objectDef.collection;
1063
1118
  existing.visibility = objectDef.visibility || manifestConfig.visibility || existing.visibility;
@@ -1068,6 +1123,8 @@ function registerFromManifest(name, objectDef, manifestPackageName) {
1068
1123
  try {
1069
1124
  registerFromManifestUntracked(name, objectDef, manifestPackageName);
1070
1125
  } finally {
1126
+ reconcileSubtypeLineage();
1127
+ applyRuntimeOverrides();
1071
1128
  bumpRegistryGeneration();
1072
1129
  }
1073
1130
  }
@@ -1076,6 +1133,9 @@ function registerFromManifestUntracked(name, objectDef, manifestPackageName) {
1076
1133
  const simpleClassName = objectDef.className || name;
1077
1134
  const qualifiedNameEarly = packageName ? createQualifiedName(packageName, simpleClassName) : objectDef.qualifiedName;
1078
1135
  const registrationKey = qualifiedNameEarly || name;
1136
+ const replacedQualifiedNames = /* @__PURE__ */ new Set();
1137
+ const manifestParent = objectDef.extendsQualified ?? objectDef.extends;
1138
+ recordSubtypeParent(registrationKey, manifestParent);
1079
1139
  const existingCanonical = getCanonicalClassName(simpleClassName);
1080
1140
  if (existingCanonical) {
1081
1141
  const existing = getClasses().get(existingCanonical);
@@ -1087,7 +1147,8 @@ function registerFromManifestUntracked(name, objectDef, manifestPackageName) {
1087
1147
  existing,
1088
1148
  existingKey: existingCanonical,
1089
1149
  registrationKey,
1090
- matchKind: "canonical-name"
1150
+ matchKind: "canonical-name",
1151
+ replacedQualifiedNames
1091
1152
  }) === "return") return;
1092
1153
  }
1093
1154
  }
@@ -1101,10 +1162,11 @@ function registerFromManifestUntracked(name, objectDef, manifestPackageName) {
1101
1162
  existing,
1102
1163
  existingKey: registrationKey,
1103
1164
  registrationKey,
1104
- matchKind: "exact-key"
1165
+ matchKind: "exact-key",
1166
+ replacedQualifiedNames
1105
1167
  }) === "return") return;
1106
1168
  }
1107
- const qualifiedExtends = objectDef.extends && packageName ? qualifyExtendsName(objectDef.extends, packageName) : objectDef.extends;
1169
+ const qualifiedExtends = manifestParent && packageName ? qualifyExtendsName(manifestParent, packageName) : manifestParent;
1108
1170
  const stubConstructor = class extends SmrtObject {
1109
1171
  static _isManifestStub = true;
1110
1172
  };
@@ -1176,6 +1238,7 @@ function registerFromManifestUntracked(name, objectDef, manifestPackageName) {
1176
1238
  collection: objectDef.collection ?? pluralizeCollection(simpleClassName),
1177
1239
  packageName,
1178
1240
  sourceFilePath: objectDef.filePath,
1241
+ replacedQualifiedNames: [...replacedQualifiedNames],
1179
1242
  extends: qualifiedExtends,
1180
1243
  extendsTypeArg: objectDef.extendsTypeArg,
1181
1244
  visibility