@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
@@ -1,26 +1,20 @@
1
- // super reference resolution — pure FQN match (FR-032 / ADR-0032)
1
+ // super reference resolution (ADR-0059)
2
2
  //
3
- // FR-032 made canonical refs fully-qualified: the YAML desugar expands every
4
- // authored relative/bare-current ref to its FQN (`expandRef`, naming-refs.ts),
5
- // and the canonical-JSON guard rejects any surviving `::`/`..::` form. So the
6
- // refs that reach this resolver are already FQN, and resolution is a pure tree
7
- // match:
8
- // Qualified "pkg::Name" → findInTree(fqn)
9
- // Bare "Name" (rare in-tree) → current package only (`<ctx>::Name`),
10
- // then literal (root-level). NO root
11
- // fallback for a packaged bare ref.
12
- // The old `::`-strip (absolute), `..::`-reduce (relative) and
13
- // bare-current-then-root-fallback branches were DELETED — that fallback was the
14
- // silent-shadowing footgun ADR-0032 removes.
3
+ // An `extends` ref resolves through the same rules as every other reference
4
+ // (`ownerCandidateKeys`, naming-refs.ts): `::Rest` root-absolute, `..::Rest`
5
+ // parent-relative, `pkg::Name` exact, bare `Name` in the declaring node's own
6
+ // file package, then root-level — never another package. The package context is
7
+ // the declaring node's effective package (`package ?? fileDefaultPackage`).
15
8
  //
16
9
  // FR-024: a ref whose final `::`-segment is dotted (`pkg::Customer.id`) targets
17
10
  // a child nested in the owner object — resolved type-scoped to the referrer.
18
11
  //
19
- // Super resolution is IMMEDIATE during parse (Java behavior). This module
20
- // provides only the lookup helper; the parser calls it inline.
12
+ // Super resolution is deferred by the loader (`resolveDeferredSupers`); the parser
13
+ // calls `resolveSuperRef` inline only when deferral is off.
21
14
 
22
15
  import type { MetaData } from "./shared/meta-data.js";
23
16
  import { PACKAGE_SEPARATOR, CHILD_REF_SEPARATOR } from "./shared/structural.js";
17
+ import { ownerCandidateKeys, RefOverDropError } from "./naming-refs.js";
24
18
  import { TYPE_IDENTITY } from "./shared/base-types.js";
25
19
  import { IDENTITY_UNIQUE_KEY_SUBTYPES } from "./core/identity/identity-constants.js";
26
20
 
@@ -29,35 +23,16 @@ import { IDENTITY_UNIQUE_KEY_SUBTYPES } from "./core/identity/identity-constants
29
23
  // ---------------------------------------------------------------------------
30
24
 
31
25
  /**
32
- * Recursively searches the tree for a node whose qualified name matches `fqn`.
33
- *
34
- * A node is matched by its own `fqn()` (covers the explicit-package and
35
- * no-package-at-all cases) OR by its EFFECTIVE qualified key
36
- * `<fileDefaultPackage>::<name>` (`MetaData.resolutionKey()`) — the
37
- * file-default package captured at PARSE time. This mirrors Java, where
38
- * `BaseMetaDataParser` folds the file-default package into the registered name
39
- * at parse time (so an object `BaseEntity` declared under `package: acme` is
40
- * registered as `acme::BaseEntity` and a fully-qualified `extends:
41
- * acme::BaseEntity` resolves) — even though TS keeps object `fqn()` bare for
42
- * the FR5d referrer-envelope cross-port contract.
43
- *
44
- * Because the resolution key is captured at parse time (not derived from the
45
- * post-merge tree), this is independent of load order AND of whether the base
46
- * node's file-default package differs from the referrer's — the cross-PACKAGE
47
- * cross-file case. No package is threaded down the walk anymore.
26
+ * The top-level node (a direct child of `root`) whose resolution key is exactly
27
+ * `key` — `<package | fileDefaultPackage>::<name>`, or the bare name for a
28
+ * root-level node. The key is captured at parse time, so the match does not depend
29
+ * on load order or on post-merge tree shape. Exact only: a bare key never matches a
30
+ * packaged node (ADR-0059 R2).
48
31
  */
49
- function findInTree(root: MetaData, fqn: string): MetaData | undefined {
50
- if (root.fqn() === fqn) return root;
51
- if (root.package === undefined && root.name !== "" && root.resolutionKey() === fqn) {
52
- return root;
53
- }
54
- // ADR-0039: own — super-resolution walk over the PHYSICAL declaration tree;
55
- // resolving accessors would be circular while the super chain is being wired.
56
- for (const child of root.ownChildren()) {
57
- const found = findInTree(child, fqn);
58
- if (found !== undefined) return found;
59
- }
60
- return undefined;
32
+ function findTopLevel(root: MetaData, key: string): MetaData | undefined {
33
+ // ADR-0039: own — super-resolution reads the PHYSICAL declaration layer; the root
34
+ // has no super, so its own children are its children.
35
+ return root.ownChildren().find((c) => c.name !== "" && c.resolutionKey() === key);
61
36
  }
62
37
 
63
38
  // ---------------------------------------------------------------------------
@@ -170,6 +145,7 @@ function parseChildTargetingRef(
170
145
  * bare lookup; a dotted ref with no `referrerScope` is unresolvable.
171
146
  *
172
147
  * @param ref - The raw super reference (e.g., "Fruit", "::pkg::Name", "..::common::id", "Customer.id")
148
+ * @throws RefOverDropError when a `..::` ref drops more segments than the package has
173
149
  * @param contextPackage - The package of the model whose super is being resolved
174
150
  * @param root - The root MetaData of the accumulating tree to search within
175
151
  * @param referrerScope - FR-024: the extending node's type — required to resolve dotted refs
@@ -211,24 +187,14 @@ export function resolveSuperRef(
211
187
  .find((c) => c.name === last && c.type === referrerScope.type);
212
188
  }
213
189
  // -------------------------------------------------------------------------
214
- // 1. FR-032 (ADR-0032): refs in the loaded tree are already fully-qualified.
215
- // The YAML desugar expanded every relative/bare-current ref to FQN
216
- // (`expandRef`), and the canonical-JSON guard rejects any surviving
217
- // `::`/`..::` form (ERR_RELATIVE_REF_IN_CANONICAL). So resolution is a
218
- // pure FQN match — the old `::`-strip (absolute), `..::`-reduce (relative)
219
- // and bare-current-then-ROOT-FALLBACK branches are deleted (the footgun).
220
- //
221
- // A qualified ref (`pkg::Name`) matches its node directly. A bare ref
222
- // (no `::`) is the rare in-tree case: a root-level/empty-package type, or
223
- // a bare ref constructed during dotted-owner recursion — resolve it in the
224
- // current package ONLY (try `<ctx>::ref`), then bare (root-level) as the
225
- // literal name. NO root fallback for a packaged bare ref.
190
+ // 1. A plain ref binds one top-level node by its form (ADR-0059 R2). An
191
+ // over-dropping `..::` throws RefOverDropError; the deferred pass reports it.
226
192
  // -------------------------------------------------------------------------
227
- if (!ref.includes(PACKAGE_SEPARATOR) && contextPackage !== "") {
228
- const inPackage = findInTree(root, `${contextPackage}${PACKAGE_SEPARATOR}${ref}`);
229
- if (inPackage !== undefined) return inPackage;
193
+ for (const key of ownerCandidateKeys(ref, contextPackage)) {
194
+ const found = findTopLevel(root, key);
195
+ if (found !== undefined) return found;
230
196
  }
231
- return findInTree(root, ref);
197
+ return undefined;
232
198
  }
233
199
 
234
200
  // ---------------------------------------------------------------------------
@@ -249,8 +215,10 @@ export interface DeferredSuperFailure {
249
215
  * target's type/subtype differs from the extending node's (loader emits
250
216
  * ERR_EXTENDS_TARGET_MISMATCH). Applies ONLY to dotted refs — top-level
251
217
  * extends behavior is unchanged.
218
+ * - "over-drop" — a `..::` ref drops more package segments than the declaring
219
+ * node's package has (ADR-0059 R2; loader emits ERR_BAD_ATTR_VALUE).
252
220
  */
253
- kind: "unresolved" | "target-mismatch";
221
+ kind: "unresolved" | "target-mismatch" | "over-drop";
254
222
  /** target-mismatch only: the resolved target's identity, for the message. */
255
223
  target?: { type: string; subType: string };
256
224
  /** target-mismatch only: the extending node's type/subtype, for the message. */
@@ -298,6 +266,20 @@ export function resolveDeferredSupers(root: MetaData): DeferredSuperFailure[] {
298
266
  if (n.superRef !== undefined) pending.push(n);
299
267
  });
300
268
 
269
+ // ADR-0059 R2: an over-dropping `..::` is a bad value, not a missing target.
270
+ const tryResolve = (
271
+ ref: string,
272
+ pkg: string,
273
+ scope?: ReferrerScope,
274
+ ): MetaData | undefined | "over-drop" => {
275
+ try {
276
+ return resolveSuperRef(ref, pkg, root, scope);
277
+ } catch (e) {
278
+ if (e instanceof RefOverDropError) return "over-drop";
279
+ throw e;
280
+ }
281
+ };
282
+
301
283
  const resolveNode = (node: MetaData): void => {
302
284
  if (node.superRef === undefined || node.superResolved !== undefined) return;
303
285
  if (attempted.has(node)) return; // already resolved-or-failed this pass — never re-report
@@ -311,15 +293,19 @@ export function resolveDeferredSupers(root: MetaData): DeferredSuperFailure[] {
311
293
  if (isChildTargetingRef(node.superRef)) {
312
294
  const parsed = parseChildTargetingRef(node.superRef);
313
295
  if (parsed !== undefined) {
314
- const ownerNode = resolveSuperRef(parsed.ownerRef, effectivePkg, root);
315
- if (ownerNode !== undefined) resolveNode(ownerNode);
296
+ const ownerNode = tryResolve(parsed.ownerRef, effectivePkg);
297
+ if (ownerNode !== undefined && ownerNode !== "over-drop") resolveNode(ownerNode);
316
298
  }
317
299
  }
318
300
 
319
301
  // FR-024: thread the referrer's type so dotted `Entity.child` refs resolve
320
302
  // type-scoped (a field ref selects fields; an identity ref identities).
321
- const target = resolveSuperRef(node.superRef, effectivePkg, root, { type: node.type });
303
+ const target = tryResolve(node.superRef, effectivePkg, { type: node.type });
322
304
 
305
+ if (target === "over-drop") {
306
+ failures.push({ nodeFqn: node.fqn(), ref: node.superRef, source: node.source, kind: "over-drop" });
307
+ return;
308
+ }
323
309
  if (target !== undefined) {
324
310
  // FR-024: a dotted ref must target a node of the SAME type and subtype
325
311
  // as the extending node. Dotted-only — top-level extends is unchanged.
@@ -2,8 +2,8 @@
2
2
  //
3
3
  // `buildRegistryManifest` answers "what must all five ports byte-match?" and deliberately
4
4
  // carves rows OUT of its answer: the `metadata.base` inheritance anchor, and the 13
5
- // TS-web-presentation `view.*` controls, which stay REGISTERED in TypeScript (the loader
6
- // must accept an authored `view.dropdown`) but are deregistered in C# and Python and
5
+ // TS-web-presentation `view.*` controls, which are REGISTERED in every port (the loader
6
+ // must accept an authored `view.dropdown`) but consumed only by TypeScript, and so are
7
7
  // excluded from the shared canonical everywhere. That carve-out is correct and documented
8
8
  // (fixtures/registry-conformance/README.md, B-2).
9
9
  //