@metaobjectsdev/metadata 1.0.12 → 1.1.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 (233) hide show
  1. package/README.md +2 -0
  2. package/dist/attr-schema-validate.d.ts.map +1 -1
  3. package/dist/attr-schema-validate.js +9 -12
  4. package/dist/attr-schema-validate.js.map +1 -1
  5. package/dist/constants.d.ts +1 -0
  6. package/dist/constants.d.ts.map +1 -1
  7. package/dist/constants.js +1 -0
  8. package/dist/constants.js.map +1 -1
  9. package/dist/core/attr/meta-attr-filter.d.ts.map +1 -1
  10. package/dist/core/attr/meta-attr-filter.js +8 -2
  11. package/dist/core/attr/meta-attr-filter.js.map +1 -1
  12. package/dist/core/attr/meta-attr.d.ts +14 -0
  13. package/dist/core/attr/meta-attr.d.ts.map +1 -1
  14. package/dist/core/attr/meta-attr.js +23 -1
  15. package/dist/core/attr/meta-attr.js.map +1 -1
  16. package/dist/core/field/shared-enum.d.ts +21 -0
  17. package/dist/core/field/shared-enum.d.ts.map +1 -0
  18. package/dist/core/field/shared-enum.js +49 -0
  19. package/dist/core/field/shared-enum.js.map +1 -0
  20. package/dist/core/identity/meta-identity.d.ts +1 -1
  21. package/dist/core/identity/meta-identity.d.ts.map +1 -1
  22. package/dist/core/identity/meta-identity.js +8 -13
  23. package/dist/core/identity/meta-identity.js.map +1 -1
  24. package/dist/core/index.d.ts +2 -0
  25. package/dist/core/index.d.ts.map +1 -1
  26. package/dist/core/index.js +3 -0
  27. package/dist/core/index.js.map +1 -1
  28. package/dist/core/object/object-constants.d.ts +14 -1
  29. package/dist/core/object/object-constants.d.ts.map +1 -1
  30. package/dist/core/object/object-constants.js +18 -0
  31. package/dist/core/object/object-constants.js.map +1 -1
  32. package/dist/core/object/object-definition.embedded.d.ts.map +1 -1
  33. package/dist/core/object/object-definition.embedded.js +80 -0
  34. package/dist/core/object/object-definition.embedded.js.map +1 -1
  35. package/dist/core/relationship/derive-m2m-fields.d.ts +1 -1
  36. package/dist/core/relationship/derive-m2m-fields.d.ts.map +1 -1
  37. package/dist/core/relationship/derive-m2m-fields.js +15 -44
  38. package/dist/core/relationship/derive-m2m-fields.js.map +1 -1
  39. package/dist/core/relationship/find-reference.d.ts.map +1 -1
  40. package/dist/core/relationship/find-reference.js +4 -2
  41. package/dist/core/relationship/find-reference.js.map +1 -1
  42. package/dist/core/relationship/resolve-relationship-reference.d.ts +6 -5
  43. package/dist/core/relationship/resolve-relationship-reference.d.ts.map +1 -1
  44. package/dist/core/relationship/resolve-relationship-reference.js +9 -7
  45. package/dist/core/relationship/resolve-relationship-reference.js.map +1 -1
  46. package/dist/core/reporting/meta-dimension.d.ts +13 -0
  47. package/dist/core/reporting/meta-dimension.d.ts.map +1 -0
  48. package/dist/core/reporting/meta-dimension.js +30 -0
  49. package/dist/core/reporting/meta-dimension.js.map +1 -0
  50. package/dist/core/reporting/meta-measure.d.ts +24 -0
  51. package/dist/core/reporting/meta-measure.d.ts.map +1 -0
  52. package/dist/core/reporting/meta-measure.js +54 -0
  53. package/dist/core/reporting/meta-measure.js.map +1 -0
  54. package/dist/core/reporting/meta-segment.d.ts +6 -0
  55. package/dist/core/reporting/meta-segment.d.ts.map +1 -0
  56. package/dist/core/reporting/meta-segment.js +13 -0
  57. package/dist/core/reporting/meta-segment.js.map +1 -0
  58. package/dist/core/reporting/report-accessors.d.ts +27 -0
  59. package/dist/core/reporting/report-accessors.d.ts.map +1 -0
  60. package/dist/core/reporting/report-accessors.js +56 -0
  61. package/dist/core/reporting/report-accessors.js.map +1 -0
  62. package/dist/core/reporting/report-describe.d.ts +59 -0
  63. package/dist/core/reporting/report-describe.d.ts.map +1 -0
  64. package/dist/core/reporting/report-describe.js +182 -0
  65. package/dist/core/reporting/report-describe.js.map +1 -0
  66. package/dist/core/reporting/report-read-model.d.ts +34 -0
  67. package/dist/core/reporting/report-read-model.d.ts.map +1 -0
  68. package/dist/core/reporting/report-read-model.js +165 -0
  69. package/dist/core/reporting/report-read-model.js.map +1 -0
  70. package/dist/core/reporting/report-shape.d.ts +103 -0
  71. package/dist/core/reporting/report-shape.d.ts.map +1 -0
  72. package/dist/core/reporting/report-shape.js +398 -0
  73. package/dist/core/reporting/report-shape.js.map +1 -0
  74. package/dist/core/reporting/reporting-constants.d.ts +65 -0
  75. package/dist/core/reporting/reporting-constants.d.ts.map +1 -0
  76. package/dist/core/reporting/reporting-constants.js +84 -0
  77. package/dist/core/reporting/reporting-constants.js.map +1 -0
  78. package/dist/core/reporting/reporting-definition.embedded.d.ts +3 -0
  79. package/dist/core/reporting/reporting-definition.embedded.d.ts.map +1 -0
  80. package/dist/core/reporting/reporting-definition.embedded.js +185 -0
  81. package/dist/core/reporting/reporting-definition.embedded.js.map +1 -0
  82. package/dist/core/requirement/resolve-claim.d.ts +8 -0
  83. package/dist/core/requirement/resolve-claim.d.ts.map +1 -1
  84. package/dist/core/requirement/resolve-claim.js +21 -0
  85. package/dist/core/requirement/resolve-claim.js.map +1 -1
  86. package/dist/core/yaml-desugar.d.ts.map +1 -1
  87. package/dist/core/yaml-desugar.js +12 -82
  88. package/dist/core/yaml-desugar.js.map +1 -1
  89. package/dist/core-types.d.ts.map +1 -1
  90. package/dist/core-types.js +28 -1
  91. package/dist/core-types.js.map +1 -1
  92. package/dist/docs-ref.d.ts +19 -0
  93. package/dist/docs-ref.d.ts.map +1 -0
  94. package/dist/docs-ref.js +37 -0
  95. package/dist/docs-ref.js.map +1 -0
  96. package/dist/errors.d.ts +1 -1
  97. package/dist/errors.d.ts.map +1 -1
  98. package/dist/errors.js +24 -6
  99. package/dist/errors.js.map +1 -1
  100. package/dist/fmt.d.ts.map +1 -1
  101. package/dist/fmt.js +3 -1
  102. package/dist/fmt.js.map +1 -1
  103. package/dist/index.d.ts +15 -4
  104. package/dist/index.d.ts.map +1 -1
  105. package/dist/index.js +18 -4
  106. package/dist/index.js.map +1 -1
  107. package/dist/loader/declared-duplicate-fields.d.ts +19 -0
  108. package/dist/loader/declared-duplicate-fields.d.ts.map +1 -0
  109. package/dist/loader/declared-duplicate-fields.js +97 -0
  110. package/dist/loader/declared-duplicate-fields.js.map +1 -0
  111. package/dist/loader/meta-data-loader.d.ts.map +1 -1
  112. package/dist/loader/meta-data-loader.js +18 -1
  113. package/dist/loader/meta-data-loader.js.map +1 -1
  114. package/dist/loader/reporting-validation.d.ts +11 -0
  115. package/dist/loader/reporting-validation.d.ts.map +1 -0
  116. package/dist/loader/reporting-validation.js +883 -0
  117. package/dist/loader/reporting-validation.js.map +1 -0
  118. package/dist/loader/resolve-references.d.ts +8 -0
  119. package/dist/loader/resolve-references.d.ts.map +1 -0
  120. package/dist/loader/resolve-references.js +132 -0
  121. package/dist/loader/resolve-references.js.map +1 -0
  122. package/dist/loader/validation-passes.d.ts.map +1 -1
  123. package/dist/loader/validation-passes.js +14 -9
  124. package/dist/loader/validation-passes.js.map +1 -1
  125. package/dist/loader/validation-registry.d.ts.map +1 -1
  126. package/dist/loader/validation-registry.js +33 -10
  127. package/dist/loader/validation-registry.js.map +1 -1
  128. package/dist/metamodel-docs/index.js +3 -3
  129. package/dist/metamodel-docs/index.js.map +1 -1
  130. package/dist/metamodel-docs/render.js +4 -4
  131. package/dist/metamodel-docs/render.js.map +1 -1
  132. package/dist/naming-refs.d.ts +102 -50
  133. package/dist/naming-refs.d.ts.map +1 -1
  134. package/dist/naming-refs.js +223 -97
  135. package/dist/naming-refs.js.map +1 -1
  136. package/dist/naming.d.ts +65 -7
  137. package/dist/naming.d.ts.map +1 -1
  138. package/dist/naming.js +98 -5
  139. package/dist/naming.js.map +1 -1
  140. package/dist/object-serializer.d.ts.map +1 -1
  141. package/dist/object-serializer.js +6 -9
  142. package/dist/object-serializer.js.map +1 -1
  143. package/dist/parser-core.d.ts.map +1 -1
  144. package/dist/parser-core.js +18 -48
  145. package/dist/parser-core.js.map +1 -1
  146. package/dist/persistence/db/db-definition.embedded.js +2 -2
  147. package/dist/persistence/db/db-definition.embedded.js.map +1 -1
  148. package/dist/persistence/source/meta-source.d.ts +5 -2
  149. package/dist/persistence/source/meta-source.d.ts.map +1 -1
  150. package/dist/persistence/source/meta-source.js +10 -6
  151. package/dist/persistence/source/meta-source.js.map +1 -1
  152. package/dist/registry-manifest-exclusions.js +2 -2
  153. package/dist/registry-manifest-exclusions.js.map +1 -1
  154. package/dist/registry-manifest.d.ts +1 -1
  155. package/dist/registry-manifest.js +1 -1
  156. package/dist/release-docs.d.ts +11 -0
  157. package/dist/release-docs.d.ts.map +1 -0
  158. package/dist/release-docs.js +48 -0
  159. package/dist/release-docs.js.map +1 -0
  160. package/dist/serializer-json.d.ts +15 -1
  161. package/dist/serializer-json.d.ts.map +1 -1
  162. package/dist/serializer-json.js +55 -17
  163. package/dist/serializer-json.js.map +1 -1
  164. package/dist/shared/base-types.d.ts +7 -1
  165. package/dist/shared/base-types.d.ts.map +1 -1
  166. package/dist/shared/base-types.js +9 -0
  167. package/dist/shared/base-types.js.map +1 -1
  168. package/dist/shared/meta-data.d.ts +10 -0
  169. package/dist/shared/meta-data.d.ts.map +1 -1
  170. package/dist/shared/meta-data.js +22 -1
  171. package/dist/shared/meta-data.js.map +1 -1
  172. package/dist/shared/meta-root.d.ts +13 -1
  173. package/dist/shared/meta-root.d.ts.map +1 -1
  174. package/dist/shared/meta-root.js +19 -1
  175. package/dist/shared/meta-root.js.map +1 -1
  176. package/dist/super-resolve.d.ts +4 -1
  177. package/dist/super-resolve.d.ts.map +1 -1
  178. package/dist/super-resolve.js +44 -65
  179. package/dist/super-resolve.js.map +1 -1
  180. package/dist/vocabulary-catalog.js +2 -2
  181. package/dist/vocabulary-catalog.js.map +1 -1
  182. package/package.json +6 -1
  183. package/src/attr-schema-validate.ts +9 -13
  184. package/src/constants.ts +1 -0
  185. package/src/core/attr/meta-attr-filter.ts +8 -1
  186. package/src/core/attr/meta-attr.ts +24 -1
  187. package/src/core/field/shared-enum.ts +53 -0
  188. package/src/core/identity/meta-identity.ts +9 -12
  189. package/src/core/index.ts +5 -0
  190. package/src/core/object/object-constants.ts +19 -0
  191. package/src/core/object/object-definition.embedded.ts +80 -0
  192. package/src/core/relationship/derive-m2m-fields.ts +15 -48
  193. package/src/core/relationship/find-reference.ts +4 -2
  194. package/src/core/relationship/resolve-relationship-reference.ts +11 -9
  195. package/src/core/reporting/meta-dimension.ts +41 -0
  196. package/src/core/reporting/meta-measure.ts +75 -0
  197. package/src/core/reporting/meta-segment.ts +14 -0
  198. package/src/core/reporting/report-accessors.ts +73 -0
  199. package/src/core/reporting/report-describe.ts +206 -0
  200. package/src/core/reporting/report-read-model.ts +177 -0
  201. package/src/core/reporting/report-shape.ts +493 -0
  202. package/src/core/reporting/reporting-constants.ts +104 -0
  203. package/src/core/reporting/reporting-definition.embedded.ts +192 -0
  204. package/src/core/requirement/resolve-claim.ts +20 -0
  205. package/src/core/yaml-desugar.ts +9 -89
  206. package/src/core-types.ts +41 -0
  207. package/src/docs-ref.ts +41 -0
  208. package/src/errors.ts +24 -6
  209. package/src/fmt.ts +3 -1
  210. package/src/index.ts +73 -5
  211. package/src/loader/declared-duplicate-fields.ts +114 -0
  212. package/src/loader/meta-data-loader.ts +25 -1
  213. package/src/loader/reporting-validation.ts +1137 -0
  214. package/src/loader/resolve-references.ts +144 -0
  215. package/src/loader/validation-passes.ts +13 -9
  216. package/src/loader/validation-registry.ts +37 -9
  217. package/src/metamodel-docs/index.ts +3 -3
  218. package/src/metamodel-docs/render.ts +4 -4
  219. package/src/naming-refs.ts +237 -94
  220. package/src/naming.ts +131 -11
  221. package/src/object-serializer.ts +7 -9
  222. package/src/parser-core.ts +19 -56
  223. package/src/persistence/db/db-definition.embedded.ts +2 -2
  224. package/src/persistence/source/meta-source.ts +10 -6
  225. package/src/registry-manifest-exclusions.ts +2 -2
  226. package/src/registry-manifest.ts +1 -1
  227. package/src/release-docs.ts +48 -0
  228. package/src/serializer-json.ts +79 -12
  229. package/src/shared/base-types.ts +9 -0
  230. package/src/shared/meta-data.ts +22 -1
  231. package/src/shared/meta-root.ts +20 -1
  232. package/src/super-resolve.ts +49 -63
  233. package/src/vocabulary-catalog.ts +2 -2
package/src/index.ts CHANGED
@@ -42,9 +42,52 @@ export * from "./core/identity/identity-constants.js";
42
42
  export * from "./core/index/index-constants.js";
43
43
  export * from "./core/requirement/requirement-constants.js";
44
44
  export { MetaRequirement } from "./core/requirement/meta-requirement.js";
45
+ export * from "./core/reporting/reporting-constants.js";
46
+ export { MetaDimension } from "./core/reporting/meta-dimension.js";
47
+ export { MetaMeasure } from "./core/reporting/meta-measure.js";
48
+ export { MetaSegment } from "./core/reporting/meta-segment.js";
49
+ export {
50
+ reportFrom,
51
+ reportSpine,
52
+ reportDimensionItems,
53
+ reportMeasureNames,
54
+ reportMeasureItemName,
55
+ reportMeasureItemOwner,
56
+ reportDerivedFieldName,
57
+ type ReportDimensionItem,
58
+ } from "./core/reporting/report-accessors.js";
59
+ export {
60
+ measureDerivedSubType,
61
+ reportShape,
62
+ reportSpineEntity,
63
+ reportSpineHops,
64
+ reportingMemberOwner,
65
+ reportingViaHops,
66
+ resolveReportingFieldRef,
67
+ resolveDimensionOf,
68
+ type ReportField,
69
+ type ReportFieldRole,
70
+ type ReportShape,
71
+ } from "./core/reporting/report-shape.js";
72
+ export { reportReadModel, reportReadSource } from "./core/reporting/report-read-model.js";
73
+ export {
74
+ describeDimension,
75
+ describeDimensionColumn,
76
+ describeFilter,
77
+ describeMeasure,
78
+ describeReportField,
79
+ describeReportRowScope,
80
+ describeReportRows,
81
+ describeRowScope,
82
+ describeSegment,
83
+ reportFieldTypeName,
84
+ reportNotServedReason,
85
+ reportingDescribedAttrs,
86
+ } from "./core/reporting/report-describe.js";
45
87
  // Shared `@implementedBy` resolution — one resolver for the CLI's requirement
46
88
  // checks and codegen's requirement-test fan-out (FR-038).
47
89
  export {
90
+ effectiveRequirementPackage,
48
91
  resolveClaim,
49
92
  resolveClaimTarget,
50
93
  resolveMember,
@@ -81,6 +124,9 @@ export {
81
124
  // Core node classes
82
125
  export { MetaObject } from "./core/object/meta-object.js";
83
126
  export { MetaField } from "./core/field/meta-field.js";
127
+ // The one authority for "which type does this enum field have" — the loader's #246
128
+ // check and every codegen site share it (ADR-0026 Amendment 1).
129
+ export { isSharedEnumDeclaration, resolveSharedEnumDeclaration } from "./core/field/shared-enum.js";
84
130
  export { MetaAttr } from "./core/attr/meta-attr.js";
85
131
 
86
132
  // Runtime object model — backing objects + FQN→factory binding (Phase A).
@@ -193,7 +239,7 @@ export { ExclusionReason } from "./registry-manifest-exclusions.js";
193
239
 
194
240
  // FR-033 S3 — metamodel doc-gen: tiered, LLM-readable docs FOR THE METAMODEL
195
241
  // (the type/subtype/attr vocabulary), generated from the strict registry.
196
- // Distinct from `meta docs --model` (which documents a user's entities).
242
+ // Distinct from the `docs` generator (which documents a user's entities).
197
243
  export {
198
244
  renderMetamodelDocs,
199
245
  buildMetamodelProvenance,
@@ -251,7 +297,22 @@ export type { FormatFileOptions, FormatFileResult } from "./fmt.js";
251
297
  export { resolveSuperRef } from "./super-resolve.js";
252
298
 
253
299
  // FR-032 (ADR-0032) — canonical reference expansion + FQN object matching.
254
- export { expandRef, isRelativeRef, refMatchesObject, resolveObjectRef, didYouMeanHint, REF_BEARING_ATTR_NAMES } from "./naming-refs.js";
300
+ export {
301
+ expandRef,
302
+ isRelativeRef,
303
+ refMatchesObject,
304
+ resolveObjectRef,
305
+ resolveRef,
306
+ lookupCanonical,
307
+ refTarget,
308
+ spellRef,
309
+ splitChildTail,
310
+ RefOverDropError,
311
+ didYouMeanHint,
312
+ didYouMeanSuperHint,
313
+ REF_BEARING_ATTR_NAMES,
314
+ } from "./naming-refs.js";
315
+ export { resolveReferences } from "./loader/resolve-references.js";
255
316
 
256
317
  // Loader hierarchy
257
318
  export { MetaDataLoader, declaredTopLevelKeys } from "./loader/meta-data-loader.js";
@@ -299,17 +360,24 @@ export type { Scope, CompiledScope } from "./scope.js";
299
360
  export { validateAttrSchema } from "./attr-schema-validate.js";
300
361
  export type { AttrSchemaValidationResult } from "./attr-schema-validate.js";
301
362
 
363
+ // Guide URLs pinned to the running release's tag (prerelease → main).
364
+ export {
365
+ DOCS_REPO_URL, DOCS_DEFAULT_REF, docsRefForVersion, docsBlobUrl, pinDocsRefs,
366
+ } from "./docs-ref.js";
367
+
302
368
  // Naming — hoisted from runtime-ts in v0.2.3 so multiple consumers (runtime-ts, migrate-ts, codegen-ts)
303
369
  // share identical name resolution. See spec §4.1.
304
370
  export {
305
- toSnakeCase, toKebabCase, pluralize,
306
- applyColumnNamingStrategy, DEFAULT_COLUMN_NAMING_STRATEGY,
371
+ toSnakeCase, toKebabCase, pluralize, pluralizeTableNameLegacy,
372
+ applyColumnNamingStrategy, DEFAULT_COLUMN_NAMING_STRATEGY, COLUMN_NAMING_STRATEGIES,
373
+ TABLE_NAMING_RULES, DEFAULT_PHYSICAL_NAMING, physicalNamingOf, applyTableNamingRule,
374
+ PHYSICAL_NAMING_MIGRATION_GUIDE, PHYSICAL_NAMING_MIGRATION_GUIDE_PATH, physicalNamingRemovedMessage,
307
375
  resolveTableName, resolveColumnName, resolveTableSchema, resolveIndexName,
308
376
  primaryRdbSource, sourceAddressKey,
309
377
  buildNameMap,
310
378
  stripPackage, packageOfResolutionKey,
311
379
  } from "./naming.js";
312
- export type { EntityNameMap, ColumnNamingStrategy } from "./naming.js";
380
+ export type { EntityNameMap, ColumnNamingStrategy, PhysicalNaming, TableNamingRule } from "./naming.js";
313
381
 
314
382
  // Retired vocabulary: the map the loader reads to explain a retirement, and the raw-document
315
383
  // rewriter `meta upgrade` drives from the SAME entries — so the error message and the fix
@@ -0,0 +1,114 @@
1
+ // declaredDuplicateFields — structural pre-parse walk for the `meta verify` field lint.
2
+ //
3
+ // Two `field.*` children with the same `name` in ONE object's `children` list load
4
+ // with no error on every port, and the loaded model keeps no trace of it: the parser's
5
+ // merge rule folds the later declaration into the first (a different subtype is
6
+ // discarded outright). So the question "was this field declared twice?" can only be
7
+ // answered from the document, before the merge — the same reason
8
+ // `declaredTopLevelKeys` exists for the overlay lint.
9
+ //
10
+ // Scope, deliberately narrow:
11
+ // - ONE children list. The same field declared in a base file and again in an
12
+ // overlay file is the overlay merge working as designed, and a subtype
13
+ // redeclaring an inherited field is an override. Neither is in one list.
14
+ // - Root-level objects only, addressed by the resolution key the parser gives them.
15
+
16
+ import { TYPE_FIELD, TYPE_METADATA, TYPE_OBJECT, SUBTYPE_ROOT } from "../shared/base-types.js";
17
+ import {
18
+ PACKAGE_SEPARATOR,
19
+ RESERVED_KEY_CHILDREN,
20
+ RESERVED_KEY_NAME,
21
+ RESERVED_KEY_PACKAGE,
22
+ TYPE_SUBTYPE_SEPARATOR,
23
+ } from "../shared/structural.js";
24
+ import { expandPackageForPath } from "../parser-core.js";
25
+ import { parseYamlWithPositions } from "../core/yaml-positions-walker.js";
26
+ import type { MetaDataFormat } from "./meta-data-source.js";
27
+
28
+ /** The YAML authoring sugar for `isArray: true` — a suffix on the wrapper key. */
29
+ const ARRAY_SUFFIX = "[]";
30
+
31
+ /** One field name declared more than once in one object's `children` list. */
32
+ export interface DeclaredDuplicateField {
33
+ /** The declaring object's resolution key (`<package>::<name>`, or the bare name). */
34
+ object: string;
35
+ /** The repeated field name. */
36
+ field: string;
37
+ /** How many times the list declares it (always 2 or more). */
38
+ count: number;
39
+ }
40
+
41
+ function isRecord(v: unknown): v is Record<string, unknown> {
42
+ return typeof v === "object" && v !== null && !Array.isArray(v);
43
+ }
44
+
45
+ /** The TYPE segment of a wrapper key: `field.string[]` and the bare `field` are both `field`. */
46
+ function wrapperType(key: string): string {
47
+ const dot = key.indexOf(TYPE_SUBTYPE_SEPARATOR);
48
+ const head = dot < 0 ? key : key.slice(0, dot);
49
+ return head.endsWith(ARRAY_SUFFIX) ? head.slice(0, -ARRAY_SUFFIX.length) : head;
50
+ }
51
+
52
+ /** A node's declared name: the body's `name`, or the body itself when YAML wrote a scalar. */
53
+ function declaredName(body: unknown): string | undefined {
54
+ const name = isRecord(body) ? body[RESERVED_KEY_NAME] : body;
55
+ return typeof name === "string" && name !== "" ? name : undefined;
56
+ }
57
+
58
+ /**
59
+ * Structurally scan a source's raw content and report every field name a root-level
60
+ * object declares more than once in its own `children` list, in document order.
61
+ *
62
+ * Malformed shapes return `[]` rather than throwing — the real parse is where a
63
+ * structural error surfaces. A syntax error does throw, as `declaredTopLevelKeys` does.
64
+ */
65
+ export function declaredDuplicateFields(
66
+ content: string,
67
+ format: MetaDataFormat,
68
+ ): ReadonlyArray<DeclaredDuplicateField> {
69
+ // Strip UTF-8 BOM if present (mirrors parseJson / parseYaml).
70
+ const normalized = content.charCodeAt(0) === 0xfeff ? content.slice(1) : content;
71
+ let parsed: unknown;
72
+ if (format === "json") parsed = JSON.parse(normalized);
73
+ else if (format === "yaml") parsed = parseYamlWithPositions(normalized).value;
74
+ else return [];
75
+ if (!isRecord(parsed)) return [];
76
+
77
+ // JSON fuses the subtype onto the root key; sigil-free YAML may write the bare type.
78
+ const rootBody = parsed[`${TYPE_METADATA}${TYPE_SUBTYPE_SEPARATOR}${SUBTYPE_ROOT}`] ?? parsed[TYPE_METADATA];
79
+ if (!isRecord(rootBody)) return [];
80
+ const rawRootPkg = rootBody[RESERVED_KEY_PACKAGE];
81
+ const rootPkg = typeof rawRootPkg === "string" ? rawRootPkg : "";
82
+ const children = rootBody[RESERVED_KEY_CHILDREN];
83
+ if (!Array.isArray(children)) return [];
84
+
85
+ const out: DeclaredDuplicateField[] = [];
86
+ for (const child of children) {
87
+ if (!isRecord(child)) continue;
88
+ for (const [wrapperKey, body] of Object.entries(child)) {
89
+ if (wrapperType(wrapperKey) !== TYPE_OBJECT || !isRecord(body)) continue;
90
+ const name = declaredName(body);
91
+ const members = body[RESERVED_KEY_CHILDREN];
92
+ if (name === undefined || !Array.isArray(members)) continue;
93
+
94
+ const counts = new Map<string, number>();
95
+ for (const member of members) {
96
+ if (!isRecord(member)) continue;
97
+ for (const [memberKey, memberBody] of Object.entries(member)) {
98
+ if (wrapperType(memberKey) !== TYPE_FIELD) continue;
99
+ const fieldName = declaredName(memberBody);
100
+ if (fieldName !== undefined) counts.set(fieldName, (counts.get(fieldName) ?? 0) + 1);
101
+ }
102
+ }
103
+
104
+ const rawOwnPkg = body[RESERVED_KEY_PACKAGE];
105
+ const pkg =
106
+ typeof rawOwnPkg === "string" && rawOwnPkg !== "" ? expandPackageForPath(rootPkg, rawOwnPkg) : rootPkg;
107
+ const object = pkg !== "" ? `${pkg}${PACKAGE_SEPARATOR}${name}` : name;
108
+ for (const [field, count] of counts) {
109
+ if (count > 1) out.push({ object, field, count });
110
+ }
111
+ }
112
+ }
113
+ return out;
114
+ }
@@ -26,6 +26,7 @@ import type { LoaderWarning } from "../source.js";
26
26
  import { codeSource, resolvedSource } from "../source.js";
27
27
  import { parseJson } from "../parser-json.js";
28
28
  import { validateDataGridSortFields, validateFilterableHasIndex, validateFilterableHasSupportedOps, validateSortableHasSupportedSubtype, validateOriginPaths, validateDerivedFieldProvidability, validateDataGridFilterValues, validateFieldObjectStorage, validateFieldMap, validateTemplatePayloadRefs, validateFieldDefaults, validateRelationships, validateOneSideReferenceResolution, validateM2MJunctionPairing, validateIndexLookupFields, validateProjectionFilter, validateRetiredRequirementLinks } from "./validation-passes.js";
29
+ import { validateReporting } from "./reporting-validation.js";
29
30
  import { runRegisteredValidation } from "./validation-registry.js";
30
31
  import { validateSourceRoles } from "../persistence/source/validate-source-roles.js";
31
32
  import { validateSourceEscapes } from "../persistence/source/validate-source-escapes.js";
@@ -35,6 +36,7 @@ import { validateFieldMutability } from "../core/field/validate-field-mutability
35
36
  import { validateEnumNormalizeAmbiguity } from "../core/field/validate-enum-normalize-ambiguity.js";
36
37
  import { validateDiscriminator } from "../core/object/validate-discriminator.js";
37
38
  import { resolveDeferredSupers, EXTENDS_TARGET_MISMATCH_RULE } from "../super-resolve.js";
39
+ import { resolveReferences } from "./resolve-references.js";
38
40
  import { validateSubtypeRules } from "../subtype-rules.js";
39
41
  import { validateMaxOccurs } from "../validate-max-occurs.js";
40
42
  import { validateIdentityPassthrough } from "../core/identity/validate-identity-passthrough.js";
@@ -43,6 +45,7 @@ import type { MetaDataFormat, MetaDataSource } from "./meta-data-source.js";
43
45
  import { InMemoryStringSource } from "./meta-data-source.js";
44
46
  import type { ParseOptions, ParseResult, PendingOverlay } from "../parser-core.js";
45
47
  import { expandPackageForPath, applyPendingOverlays } from "../parser-core.js";
48
+ import { didYouMeanSuperHint } from "../naming-refs.js";
46
49
 
47
50
  // Local mirror of DirectorySource's options shape. Deliberately inlined here
48
51
  // (instead of `import type`'d from ./sources/directory-source.js) so the
@@ -589,9 +592,22 @@ export class MetaDataLoader {
589
592
  );
590
593
  continue;
591
594
  }
595
+ if (failure.kind === "over-drop") {
596
+ // ADR-0059 R2 — `..::` dropped more segments than the package has.
597
+ errors.push(
598
+ new ParseError(
599
+ `the extends ref '${failure.ref}' on ${failure.nodeFqn} climbs above the root package — each '..::' drops one segment of the declaring package`,
600
+ {
601
+ code: "ERR_BAD_ATTR_VALUE",
602
+ source: resolvedSource(failure.source, failure.nodeFqn, failure.ref),
603
+ },
604
+ ),
605
+ );
606
+ continue;
607
+ }
592
608
  errors.push(
593
609
  new ParseError(
594
- `the SuperClass '${failure.ref}' does not exist (referenced by ${failure.nodeFqn})`,
610
+ `the SuperClass '${failure.ref}' does not exist (referenced by ${failure.nodeFqn})${didYouMeanSuperHint(root, failure.ref)}`,
595
611
  {
596
612
  code: "ERR_UNRESOLVED_SUPER",
597
613
  source: resolvedSource(failure.source, failure.nodeFqn, failure.ref),
@@ -646,6 +662,10 @@ export class MetaDataLoader {
646
662
  // an aggregate-derived or dangling ref is fail-closed (ERR_BAD_ATTR_FILTER).
647
663
  errors.push(...validateProjectionFilter(root));
648
664
 
665
+ // FR-044 — reporting vocabulary cross-node rules (dimensions, measures,
666
+ // segments, reports, relative-date filter values).
667
+ errors.push(...validateReporting(root));
668
+
649
669
  // FR-017 — M:N relationship validation (deferred-resolution): @through names a
650
670
  // junction declaring two identity.reference children; @sourceRefField matches one;
651
671
  // @symmetric is self-join-only + mutually exclusive with @sourceRefField; M:N attrs
@@ -745,6 +765,10 @@ export class MetaDataLoader {
745
765
  // finite number, boolean → true|false). Enum @default membership is validated
746
766
  // by validateAttrSchema (Check 5). Cross-port parity with Java/Python/C#.
747
767
  errors.push(...validateFieldDefaults(root));
768
+
769
+ // ADR-0059 R5 — after the last validation pass, before freeze: resolve every
770
+ // reference once, record its target and rewrite it to its canonical spelling.
771
+ resolveReferences(root);
748
772
  }
749
773
 
750
774
  // If nothing parsed successfully, synthesize an empty root so callers