@metaobjectsdev/metadata 1.0.13 → 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 +17 -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 +42 -7
  137. package/dist/naming.d.ts.map +1 -1
  138. package/dist/naming.js +43 -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 -3
  149. package/dist/persistence/source/meta-source.d.ts.map +1 -1
  150. package/dist/persistence/source/meta-source.js +8 -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 +17 -6
  209. package/src/fmt.ts +3 -1
  210. package/src/index.ts +72 -4
  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 +75 -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 +8 -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
@@ -0,0 +1,144 @@
1
+ // ADR-0059 R5 — resolve every reference once, after validation and before freeze.
2
+ //
3
+ // Sources do not interpret references (R1): YAML and canonical JSON hand the loader
4
+ // each reference string exactly as written. The validation passes resolve those
5
+ // authored strings through the shared resolver and report failures with their own
6
+ // codes. This pass then walks the physical tree once and, for every reference that
7
+ // resolves, records the target and rewrites the value to its canonical spelling (R6),
8
+ // keeping the authored string beside it. After the pass every consumer reads values
9
+ // that mean the same thing whatever package they are read from, and the serializer
10
+ // writes them as they are.
11
+ //
12
+ // A reference that does not resolve is left exactly as written: validation has
13
+ // already reported it.
14
+
15
+ import type { MetaData, AttrValue } from "../shared/meta-data.js";
16
+ import { MetaAttr } from "../core/attr/meta-attr.js";
17
+ import { TYPE_DIMENSION } from "../shared/base-types.js";
18
+ import { REPORTING_ATTR_OF, REPORTING_ATTR_VIA } from "../core/reporting/reporting-constants.js";
19
+ import {
20
+ OBJECT_REPORT_ATTR_FROM,
21
+ OBJECT_REPORT_ATTR_SPINE,
22
+ OBJECT_SUBTYPE_REPORT,
23
+ } from "../core/object/object-constants.js";
24
+ import { TYPE_OBJECT } from "../shared/base-types.js";
25
+ import {
26
+ REF_BEARING_ATTR_NAMES,
27
+ effectivePackageOf,
28
+ resolveObjectRef,
29
+ spellRef,
30
+ splitChildTail,
31
+ topLevelNodeOf,
32
+ } from "../naming-refs.js";
33
+ import { resolveSuperRef } from "../super-resolve.js";
34
+ import { dimensionViaTerminal } from "./reporting-validation.js";
35
+
36
+ /** One resolved reference: its owner object and the canonical spelling. */
37
+ interface Resolved {
38
+ readonly target: MetaData;
39
+ readonly canonical: string;
40
+ }
41
+
42
+ /** Resolve one reference string's owner in `refPkg`, and spell it canonically. Root-level
43
+ * targets are spelled `::Name` unless both the resolution package and the declaring
44
+ * package are root-level, so a consumer reading from either package binds the same node. */
45
+ function resolveOne(root: MetaData, value: string, refPkg: string, declPkg: string): Resolved | undefined {
46
+ const { owner, tail } = splitChildTail(value);
47
+ const target = resolveObjectRef(root, owner, refPkg).node;
48
+ if (target === undefined) return undefined;
49
+ return { target, canonical: spellRef(target, refPkg !== "" ? refPkg : declPkg, tail) };
50
+ }
51
+
52
+ /** R3 — the package an own reference attribute of `node` resolves in. */
53
+ function referrerPackage(root: MetaData, node: MetaData, attr: string, declPkg: string): string {
54
+ // `@of` on a dimension that walks `@via`: the package of the entity the walk reaches.
55
+ if (node.type === TYPE_DIMENSION && attr === REPORTING_ATTR_OF) {
56
+ // ADR-0039: resolving — the @via that governs this @of may be inherited.
57
+ const via = node.attr(REPORTING_ATTR_VIA);
58
+ const declaring = node.parent;
59
+ if (typeof via === "string" && via !== "" && declaring !== undefined) {
60
+ const terminal = dimensionViaTerminal(root, declaring, via);
61
+ return terminal !== undefined ? effectivePackageOf(terminal) : declPkg;
62
+ }
63
+ }
64
+ // `@spine` on a report: the package of the `@from` entity.
65
+ if (node.type === TYPE_OBJECT && node.subType === OBJECT_SUBTYPE_REPORT && attr === OBJECT_REPORT_ATTR_SPINE) {
66
+ // ADR-0039: resolving — @from may be inherited.
67
+ const from = node.attr(OBJECT_REPORT_ATTR_FROM);
68
+ if (typeof from === "string" && from !== "") {
69
+ const fromNode = resolveObjectRef(root, from, declPkg).node;
70
+ if (fromNode !== undefined) return effectivePackageOf(fromNode);
71
+ }
72
+ }
73
+ return declPkg;
74
+ }
75
+
76
+ function resolveAttr(root: MetaData, node: MetaData, attr: MetaAttr, declPkg: string): void {
77
+ const value = attr.value;
78
+ const refPkg = referrerPackage(root, node, attr.name, declPkg);
79
+ if (typeof value === "string") {
80
+ if (value === "") return;
81
+ const r = resolveOne(root, value, refPkg, declPkg);
82
+ if (r === undefined) return;
83
+ attr.resolvedTarget = r.target;
84
+ if (r.canonical !== value) {
85
+ attr.authoredValue ??= value;
86
+ node.setAttr(attr.name, r.canonical);
87
+ }
88
+ return;
89
+ }
90
+ if (Array.isArray(value) && value.every((v) => typeof v === "string")) {
91
+ const items = value as readonly string[];
92
+ const resolved = items.map((v) => (v === "" ? undefined : resolveOne(root, v, refPkg, declPkg)));
93
+ if (resolved.every((r) => r === undefined)) return;
94
+ attr.resolvedTarget = resolved.map((r) => r?.target);
95
+ const canonical: AttrValue = items.map((v, i) => resolved[i]?.canonical ?? v);
96
+ if (canonical.some((v, i) => v !== items[i])) {
97
+ attr.authoredValue ??= [...items];
98
+ node.setAttr(attr.name, canonical);
99
+ }
100
+ }
101
+ }
102
+
103
+ /** Canonical `extends`: the owner spelled from the declaring node's package, tail kept. */
104
+ function resolveExtends(root: MetaData, node: MetaData): void {
105
+ const ref = node.superRef;
106
+ if (ref === undefined || node.superResolved === undefined) return;
107
+ const pkg = effectivePackageOf(node);
108
+ const { owner, tail } = splitChildTail(ref);
109
+ let ownerNode: MetaData | undefined;
110
+ try {
111
+ ownerNode = resolveSuperRef(owner, pkg, root);
112
+ } catch {
113
+ return; // an over-drop never resolved, so superResolved would be unset
114
+ }
115
+ if (ownerNode === undefined) return;
116
+ const canonical = spellRef(ownerNode, pkg, tail);
117
+ if (canonical === ref) return;
118
+ node.authoredSuperRef ??= ref;
119
+ node.setSuper(canonical);
120
+ }
121
+
122
+ /**
123
+ * Resolve every own reference attribute (ADR-0059 R4) and every `extends` in the
124
+ * tree, record the targets, and rewrite resolved values to their canonical spelling.
125
+ * Must run after the last validation pass and before `freeze()`.
126
+ */
127
+ export function resolveReferences(root: MetaData): void {
128
+ const visit = (node: MetaData): void => {
129
+ if (node !== root) {
130
+ resolveExtends(root, node);
131
+ // R3 default: the effective package of the top-level node that physically
132
+ // declares the attribute. Own attributes are declared here, by definition.
133
+ const declPkg = effectivePackageOf(topLevelNodeOf(node));
134
+ // ADR-0039: own — this pass rewrites the declared-here layer; an inherited
135
+ // attribute is resolved once, on the node that declares it.
136
+ for (const attr of node.ownMetaAttrs()) {
137
+ if (REF_BEARING_ATTR_NAMES.has(attr.name)) resolveAttr(root, node, attr, declPkg);
138
+ }
139
+ }
140
+ // ADR-0039: own — structural walk over the physical declaration tree.
141
+ for (const child of node.ownChildren()) visit(child);
142
+ };
143
+ visit(root);
144
+ }
@@ -15,7 +15,7 @@ import type { MetaObject } from "../core/object/meta-object.js";
15
15
  import type { MetaReferenceIdentity } from "../core/identity/meta-identity.js";
16
16
  import { contradictionHint, contradictionsFor } from "../attr-contradictions.js";
17
17
  import { ParseError, type ErrorCode } from "../errors.js";
18
- import { resolveObjectRef, didYouMeanHint } from "../naming-refs.js";
18
+ import { resolveObjectRef, didYouMeanHint, refTarget } from "../naming-refs.js";
19
19
  import { PACKAGE_SEPARATOR, CHILD_REF_SEPARATOR } from "../shared/structural.js";
20
20
  import { resolvedSource, type ErrorSource } from "../source.js";
21
21
  import {
@@ -138,7 +138,6 @@ import type { MetaRelationship } from "../core/relationship/meta-relationship.js
138
138
  // Rule (f) runs the REAL M:N derivation so the loader and codegen cannot drift.
139
139
  import { deriveM2MFields, M2MDerivationError } from "../core/relationship/derive-m2m-fields.js";
140
140
  import { isReadOnlySource, isWritableSource } from "../shared/node-guards.js";
141
- import { stripPackage } from "../naming.js";
142
141
  import {
143
142
  FILTER_COMPOSE_OR,
144
143
  FILTER_COMPOSE_AND,
@@ -957,8 +956,8 @@ function _inferViaSingleHop(
957
956
  .filter((c) => c.type === TYPE_RELATIONSHIP)
958
957
  .filter((rel) => {
959
958
  // ADR-0039: resolving — a relationship may inherit @objectRef via extends.
960
- const ref = rel.attr(RELATIONSHIP_ATTR_OBJECT_REF);
961
- return typeof ref === "string" && stripPackage(ref) === targetEntity.name;
959
+ // ADR-0059 R7: compare the bound target, never a short name.
960
+ return refTarget(rel, RELATIONSHIP_ATTR_OBJECT_REF) === targetEntity;
962
961
  });
963
962
  // FR5d — referrer is `<host-FQN>::<fieldName>`, target is the from/of ref
964
963
  // whose implicit path could not be resolved.
@@ -2207,7 +2206,11 @@ export function validateOneSideReferenceResolution(root: MetaRoot): ParseError[]
2207
2206
  const objectRef = rel.attr(RELATIONSHIP_ATTR_OBJECT_REF);
2208
2207
  if (typeof objectRef !== "string" || objectRef === "") continue;
2209
2208
 
2210
- const candidates = referenceCandidatesFor(obj, objectRef);
2209
+ // ADR-0059 R7: match references by the bound target node. An unresolved
2210
+ // @objectRef is reported by its own pass.
2211
+ const targetNode = refTarget(rel, RELATIONSHIP_ATTR_OBJECT_REF);
2212
+ if (targetNode === undefined) continue;
2213
+ const candidates = referenceCandidatesFor(obj, targetNode);
2211
2214
 
2212
2215
  const sourceRefField = rel.attr(RELATIONSHIP_ATTR_SOURCE_REF_FIELD);
2213
2216
  const declared = typeof sourceRefField === "string" && sourceRefField !== ""
@@ -2237,7 +2240,7 @@ export function validateOneSideReferenceResolution(root: MetaRoot): ParseError[]
2237
2240
  // No @sourceRefField declared: ambiguity only exists with 2+ candidates —
2238
2241
  // resolveRelationshipReference's name-pairing step (ladder step 3) decides.
2239
2242
  if (candidates.length <= 1) continue;
2240
- const resolved = resolveRelationshipReference(obj, rel.name, objectRef);
2243
+ const resolved = resolveRelationshipReference(obj, rel.name, targetNode);
2241
2244
  if (resolved) continue;
2242
2245
 
2243
2246
  errors.push(
@@ -2706,9 +2709,10 @@ function checkProjectionFilterRefs(
2706
2709
  // Resolution of the reference itself is `verify`'s job (it owns every other
2707
2710
  // @implementedBy-style resolution) — the loader owns the shape.
2708
2711
  //
2709
- // Runs in every port. `requirement.*` gate logic otherwise lives only in the TS
2710
- // CLI, which is exactly why THIS rule belongs in the loader: a Java or Python
2711
- // estate would otherwise be free to author the shape the rule exists to prevent.
2712
+ // Runs in every port. The requirement gate runs in every port's `verify` since
2713
+ // ADR-0057 (when this rule was written it ran only in the TS CLI), yet the rule
2714
+ // stays in the loader: a shape the loader refuses is unreachable in every port
2715
+ // and in every program that loads the model, whether or not anyone runs `verify`.
2712
2716
  //
2713
2717
  // ADR-0039: children()/attr() throughout — never own* — so a requirement that
2714
2718
  // inherits its status through `extends` is judged on its EFFECTIVE status.
@@ -8,9 +8,13 @@
8
8
 
9
9
  import type { MetaData } from "../shared/meta-data.js";
10
10
  import { ParseError } from "../errors.js";
11
- import { didYouMeanHint } from "../naming-refs.js";
11
+ import {
12
+ didYouMeanHint,
13
+ ownerCandidateKeys,
14
+ referrerPackageFor,
15
+ RefOverDropError,
16
+ } from "../naming-refs.js";
12
17
  import { TYPE_OBJECT } from "../shared/base-types.js";
13
- import { PACKAGE_SEPARATOR } from "../shared/structural.js";
14
18
  import type { TypeRegistry } from "../registry.js";
15
19
  import type { LoaderCode, SymbolTable, ValidationContext } from "../validation-types.js";
16
20
 
@@ -38,15 +42,25 @@ class SymbolTableImpl implements SymbolTable {
38
42
  return t;
39
43
  }
40
44
 
41
- /** ADR-0042 package-local resolution within the `type` bucket: FQN → exact
42
- * resolution-key match; bare → the referrer's own package (`<referrerPkg>::<ref>`),
43
- * else a root-level node of that type. */
45
+ /** ADR-0059 R2 resolution within the `type` bucket: `::Rest` root-absolute,
46
+ * `..::Rest` parent-relative, `pkg::Name` exact, bare `Name` in the referrer's own
47
+ * package then root-level. Exact keys only. An over-dropping `..::` resolves to
48
+ * nothing here; the walk reports it as ERR_BAD_ATTR_VALUE. */
44
49
  resolve(type: string, ref: string, referrerPkg: string): MetaData | undefined {
45
50
  const bucket = this.byType.get(type);
46
51
  if (bucket === undefined) return undefined;
47
- if (ref.includes(PACKAGE_SEPARATOR)) return bucket.get(ref);
48
- const localKey = referrerPkg !== "" ? `${referrerPkg}${PACKAGE_SEPARATOR}${ref}` : ref;
49
- return bucket.get(localKey) ?? bucket.get(ref);
52
+ let keys: readonly string[];
53
+ try {
54
+ keys = ownerCandidateKeys(ref, referrerPkg);
55
+ } catch (e) {
56
+ if (e instanceof RefOverDropError) return undefined;
57
+ throw e;
58
+ }
59
+ for (const key of keys) {
60
+ const hit = bucket.get(key);
61
+ if (hit !== undefined) return hit;
62
+ }
63
+ return undefined;
50
64
  }
51
65
 
52
66
  resolveObject(ref: string, referrerPkg: string): MetaData | undefined {
@@ -94,7 +108,21 @@ export function runRegisteredValidation(root: MetaData, registry: TypeRegistry):
94
108
  const raw = node.attr(desc.attr);
95
109
  if (typeof raw !== "string" || raw === "") continue; // absence is the required-attr pass's job
96
110
  const entityRef = desc.dottedFieldPath ? (raw.split(".")[0] ?? raw) : raw;
97
- const target = ctx.symbols.resolve(desc.targetType, entityRef, pkg);
111
+ // ADR-0059 R3: an inherited reference resolves in the package of the
112
+ // top-level node that physically declares it, not the inheritor's.
113
+ const refPkg = referrerPackageFor(node, desc.attr);
114
+ try {
115
+ ownerCandidateKeys(entityRef, refPkg);
116
+ } catch (e) {
117
+ if (!(e instanceof RefOverDropError)) throw e;
118
+ ctx.error(
119
+ "ERR_BAD_ATTR_VALUE",
120
+ node,
121
+ `${node.type}.${node.subType} "${node.name}" @${desc.attr} "${raw}" climbs above the root package — each '..::' drops one segment of the declaring package.`,
122
+ );
123
+ continue;
124
+ }
125
+ const target = ctx.symbols.resolve(desc.targetType, entityRef, refPkg);
98
126
  // Qualify the node name with its owning entity (e.g. "Order.items") so the error is
99
127
  // locatable from the message alone, not just the source envelope.
100
128
  const qname = node.parent?.name ? `${node.parent.name}.${node.name}` : node.name;
@@ -1,10 +1,10 @@
1
1
  // FR-033 S3 — metamodel doc-gen public surface.
2
2
  //
3
3
  // Documents the METAMODEL ITSELF (the type/subtype/attr vocabulary of the strict
4
- // registry) as tiered, LLM-readable markdown — distinct from `meta docs --model`
4
+ // registry) as tiered, LLM-readable markdown — distinct from the `docs` generator
5
5
  // (which documents a user's entities). The renderer is a pure, deterministic
6
- // function over the composed registry + a provenance lens; file I/O lives in the
7
- // CLI.
6
+ // function over the composed registry + a provenance lens; the `metamodel-docs`
7
+ // generator in codegen-ts writes its pages.
8
8
 
9
9
  import type { TypeRegistry } from "../registry.js";
10
10
  import { coreProviders } from "../core-types.js";
@@ -1,8 +1,8 @@
1
1
  // FR-033 S3 — the metamodel doc renderer (pure, deterministic, byte-stable).
2
2
  //
3
3
  // Documents the METAMODEL ITSELF — the type/subtype/attr vocabulary of the
4
- // strict registry — for an LLM (and humans). This is distinct from `meta docs
5
- // --model`, which documents a USER's entities. The output is a tiered markdown
4
+ // strict registry — for an LLM (and humans). This is distinct from the `docs`
5
+ // generator (`docsFile()`), which documents a USER's entities. The output is a tiered markdown
6
6
  // tree:
7
7
  //
8
8
  // INDEX.md every type.subType + one-liner + link (always-on map)
@@ -24,7 +24,7 @@ import { CHILD_RULE_WILDCARD } from "../shared/structural.js";
24
24
  import { SUBTYPE_BASE } from "../shared/base-types.js";
25
25
 
26
26
  /** The regeneration command, named in every file's DO-NOT-EDIT header. */
27
- const REGEN_COMMAND = "meta docs --metamodel";
27
+ const REGEN_COMMAND = "meta gen (the metamodel-docs generator, metamodelDocsFile())";
28
28
 
29
29
  /** ASCII codepoint compare — locale-independent, byte-stable. */
30
30
  function compare(a: string, b: string): number {
@@ -196,7 +196,7 @@ function renderIndex(defs: readonly TypeDefinition[]): string {
196
196
  "# MetaObjects Metamodel — Index\n",
197
197
  "This documents the **metamodel itself** — the type / subtype / attribute",
198
198
  "vocabulary the loader accepts — generated from the strict registry. It is",
199
- "NOT documentation of a user's entities (that is `meta docs --model`).\n",
199
+ "NOT documentation of a user's entities (that is the `docs` generator, `docsFile()`).\n",
200
200
  "Follow a link into `types/<family>.md` for the full attribute table, allowed",
201
201
  "children, and cardinality of a subtype. Universal documentation attributes",
202
202
  "(`@description`/`@title`/…) apply to every node and are listed once in",