@astrale-os/kernel-dsl 1.0.0-beta.2 → 1.0.0-beta.20

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 (307) hide show
  1. package/dist/v1/addressing/class-key.js +3 -3
  2. package/dist/v1/addressing/definition-ref.js +21 -37
  3. package/dist/v1/addressing/domain-dependency.d.ts +0 -6
  4. package/dist/v1/addressing/domain-dependency.js +1 -6
  5. package/dist/v1/addressing/key.d.ts +4 -1
  6. package/dist/v1/addressing/key.js +23 -3
  7. package/dist/v1/addressing/ordering.d.ts +2 -0
  8. package/dist/v1/addressing/ordering.js +4 -0
  9. package/dist/v1/addressing/patterns.d.ts +1 -1
  10. package/dist/v1/addressing/patterns.js +2 -6
  11. package/dist/v1/builder/callable/authoring.d.ts +11 -5
  12. package/dist/v1/builder/callable/authoring.js +2 -0
  13. package/dist/v1/builder/class/authoring.d.ts +94 -224
  14. package/dist/v1/builder/class/authoring.js +31 -33
  15. package/dist/v1/builder/class/handle.d.ts +27 -0
  16. package/dist/v1/builder/class/handle.js +1 -0
  17. package/dist/v1/builder/class/input.d.ts +159 -0
  18. package/dist/v1/builder/class/projection.d.ts +129 -0
  19. package/dist/v1/builder/class/projection.js +1 -0
  20. package/dist/v1/builder/class/property.d.ts +3 -9
  21. package/dist/v1/builder/class/property.js +1 -0
  22. package/dist/v1/builder/core/authoring.d.ts +1 -1
  23. package/dist/v1/builder/index.d.ts +5 -2
  24. package/dist/v1/builder/lowering/callable.js +1 -0
  25. package/dist/v1/builder/lowering/class.d.ts +9 -1
  26. package/dist/v1/builder/lowering/class.js +62 -17
  27. package/dist/v1/builder/lowering/policy.js +2 -0
  28. package/dist/v1/builder/lowering/property-keys.d.ts +27 -0
  29. package/dist/v1/builder/lowering/property-keys.js +108 -0
  30. package/dist/v1/builder/lowering/schema/compile.js +11 -6
  31. package/dist/v1/builder/lowering/schema/context.d.ts +9 -1
  32. package/dist/v1/builder/lowering/schema/context.js +36 -4
  33. package/dist/v1/builder/lowering/schema/lifetime.d.ts +11 -0
  34. package/dist/v1/builder/lowering/schema/lifetime.js +55 -0
  35. package/dist/v1/builder/lowering/value/path.d.ts +1 -1
  36. package/dist/v1/builder/lowering/value/path.js +2 -4
  37. package/dist/v1/builder/lowering/value/zod.js +1 -3
  38. package/dist/v1/builder/policy/authoring.d.ts +85 -5
  39. package/dist/v1/builder/policy/authoring.js +107 -68
  40. package/dist/v1/builder/schema/define.d.ts +0 -1
  41. package/dist/v1/builder/schema/diagnostic.d.ts +3 -2
  42. package/dist/v1/builder/schema/diagnostic.js +5 -10
  43. package/dist/v1/builder/schema/input.d.ts +1 -1
  44. package/dist/v1/builder/schema/projection/callable.d.ts +7 -5
  45. package/dist/v1/builder/schema/projection/class.d.ts +118 -15
  46. package/dist/v1/builder/schema/projection/core-input.d.ts +2 -1
  47. package/dist/v1/builder/schema/projection/identity.d.ts +2 -1
  48. package/dist/v1/builder/schema/projection/model.d.ts +4 -2
  49. package/dist/v1/builder/schema/projection/property.d.ts +1 -1
  50. package/dist/v1/builder/schema/projection/resolved-class.d.ts +2 -1
  51. package/dist/v1/builder/schema/projection.d.ts +1 -1
  52. package/dist/v1/builder/value/full-match.d.ts +0 -1
  53. package/dist/v1/builder/value/full-match.js +0 -1
  54. package/dist/v1/builder/value/path-metadata.d.ts +1 -1
  55. package/dist/v1/builder/value/path.d.ts +1 -1
  56. package/dist/v1/bundle/codec.js +11 -13
  57. package/dist/v1/bundle/diagnostic.d.ts +2 -0
  58. package/dist/v1/bundle/diagnostic.js +9 -7
  59. package/dist/v1/bundle/model.js +1 -1
  60. package/dist/v1/bundle/structure.js +4 -6
  61. package/dist/v1/compiled/admission/accept.js +4 -10
  62. package/dist/v1/compiled/admission/closure.js +2 -2
  63. package/dist/v1/compiled/admission/diagnostic.d.ts +1 -1
  64. package/dist/v1/compiled/admission/diagnostic.js +1 -3
  65. package/dist/v1/compiled/admission/revision.d.ts +9 -1
  66. package/dist/v1/compiled/admission/revision.js +6 -3
  67. package/dist/v1/compiled/admission/semantics/class.d.ts +4 -1
  68. package/dist/v1/compiled/admission/semantics/class.js +37 -12
  69. package/dist/v1/compiled/admission/semantics/core.d.ts +1 -24
  70. package/dist/v1/compiled/admission/semantics/core.js +56 -24
  71. package/dist/v1/compiled/admission/semantics/edge.d.ts +2 -4
  72. package/dist/v1/compiled/admission/semantics/edge.js +6 -65
  73. package/dist/v1/compiled/admission/semantics/policy/callable.js +0 -2
  74. package/dist/v1/compiled/admission/semantics/policy/contracts.d.ts +5 -20
  75. package/dist/v1/compiled/admission/semantics/policy/contracts.js +8 -21
  76. package/dist/v1/compiled/admission/semantics/policy/parity.js +40 -43
  77. package/dist/v1/compiled/admission/semantics/policy/pattern.d.ts +4 -1
  78. package/dist/v1/compiled/admission/semantics/policy/pattern.js +4 -16
  79. package/dist/v1/compiled/admission/semantics/policy/typing.d.ts +2 -24
  80. package/dist/v1/compiled/admission/semantics/policy/typing.js +19 -201
  81. package/dist/v1/compiled/admission/wire/callable.js +11 -1
  82. package/dist/v1/compiled/admission/wire/class.js +73 -21
  83. package/dist/v1/compiled/admission/wire/policy.d.ts +4 -3
  84. package/dist/v1/compiled/admission/wire/policy.js +8 -7
  85. package/dist/v1/compiled/compiler/compile.js +8 -8
  86. package/dist/v1/compiled/diagnostic.js +2 -3
  87. package/dist/v1/compiled/loader/load.d.ts +3 -2
  88. package/dist/v1/compiled/loader/load.js +11 -45
  89. package/dist/v1/domain/create.js +5 -6
  90. package/dist/v1/domain/model/domain.d.ts +2 -7
  91. package/dist/v1/domain/model/input.d.ts +2 -1
  92. package/dist/v1/domain/namespace/member-collection.js +4 -6
  93. package/dist/v1/domain/projection/classes.js +4 -1
  94. package/dist/v1/domain/validation/create.d.ts +6 -3
  95. package/dist/v1/domain/validation/create.js +21 -69
  96. package/dist/v1/index.d.ts +2 -1
  97. package/dist/v1/language/.spec/schemas/draft-2020-12.schema.json +462 -0
  98. package/dist/v1/language/.spec/schemas/value-schema.schema.json +22 -0
  99. package/dist/v1/language/callable/admission.d.ts +15 -0
  100. package/dist/v1/language/callable/admission.js +43 -0
  101. package/dist/v1/language/callable/model/callable.d.ts +10 -0
  102. package/dist/v1/language/callable/resolved.d.ts +16 -3
  103. package/dist/v1/language/class/inheritance.d.ts +36 -5
  104. package/dist/v1/language/class/inheritance.js +87 -1
  105. package/dist/v1/language/class/lifetime.d.ts +50 -11
  106. package/dist/v1/language/class/lifetime.js +89 -20
  107. package/dist/v1/language/class/model/class.d.ts +45 -9
  108. package/dist/v1/language/class/model/edge.d.ts +31 -2
  109. package/dist/v1/language/class/model/property.d.ts +16 -7
  110. package/dist/v1/language/class/property-values.js +2 -4
  111. package/dist/v1/language/class/unique.d.ts +143 -0
  112. package/dist/v1/language/class/unique.js +264 -0
  113. package/dist/v1/language/core/facts.d.ts +85 -0
  114. package/dist/v1/language/core/facts.js +116 -0
  115. package/dist/v1/language/definition/metadata.d.ts +5 -0
  116. package/dist/v1/language/definition/metadata.js +7 -0
  117. package/dist/v1/language/freeze.d.ts +5 -0
  118. package/dist/v1/{schema/canonical → language}/freeze.js +4 -0
  119. package/dist/v1/language/index.d.ts +7 -2
  120. package/dist/v1/language/index.js +5 -1
  121. package/dist/v1/language/limits.d.ts +64 -0
  122. package/dist/v1/language/limits.js +60 -0
  123. package/dist/v1/language/policy/analysis/branches.d.ts +8 -0
  124. package/dist/v1/language/policy/analysis/branches.js +2 -1
  125. package/dist/v1/language/policy/analysis/budgets.d.ts +45 -12
  126. package/dist/v1/language/policy/analysis/budgets.js +133 -19
  127. package/dist/v1/language/policy/analysis/checks.js +3 -2
  128. package/dist/v1/language/policy/analysis/typing.d.ts +51 -0
  129. package/dist/v1/language/policy/analysis/typing.js +455 -0
  130. package/dist/v1/language/policy/model/policy.d.ts +49 -9
  131. package/dist/v1/language/policy/model/policy.js +14 -0
  132. package/dist/v1/language/policy/normalization/normalize.d.ts +6 -6
  133. package/dist/v1/language/policy/normalization/normalize.js +22 -21
  134. package/dist/v1/language/validation/diagnostic.d.ts +15 -1
  135. package/dist/v1/language/validation/diagnostic.js +21 -0
  136. package/dist/v1/language/validation/rule.d.ts +45 -0
  137. package/dist/v1/language/validation/rule.js +109 -0
  138. package/dist/v1/language/value/compile/fields.js +4 -8
  139. package/dist/v1/language/value/evaluate/program.d.ts +2 -1
  140. package/dist/v1/language/value/evaluate/program.js +2 -2
  141. package/dist/v1/language/value/evaluate/validate.d.ts +2 -2
  142. package/dist/v1/language/value/evaluate/validate.js +6 -2
  143. package/dist/v1/language/value/evaluate/validity.optimization.d.ts +14 -0
  144. package/dist/v1/language/value/evaluate/validity.optimization.js +342 -0
  145. package/dist/v1/language/value/inclusion/arrays.d.ts +3 -0
  146. package/dist/v1/language/value/inclusion/arrays.js +85 -0
  147. package/dist/v1/language/value/inclusion/assertions.d.ts +18 -0
  148. package/dist/v1/language/value/inclusion/assertions.js +29 -0
  149. package/dist/v1/language/value/inclusion/combinators.d.ts +3 -0
  150. package/dist/v1/language/value/inclusion/combinators.js +67 -0
  151. package/dist/v1/language/value/inclusion/equivalence.d.ts +4 -0
  152. package/dist/v1/language/value/inclusion/equivalence.js +74 -0
  153. package/dist/v1/language/value/inclusion/evidence.d.ts +34 -0
  154. package/dist/v1/language/value/inclusion/evidence.js +138 -0
  155. package/dist/v1/language/value/inclusion/includes.d.ts +17 -0
  156. package/dist/v1/language/value/inclusion/includes.js +25 -719
  157. package/dist/v1/language/value/inclusion/keywords.d.ts +5 -0
  158. package/dist/v1/language/value/inclusion/keywords.js +31 -0
  159. package/dist/v1/language/value/inclusion/kinds.d.ts +17 -0
  160. package/dist/v1/language/value/inclusion/kinds.js +57 -0
  161. package/dist/v1/language/value/inclusion/location.d.ts +24 -0
  162. package/dist/v1/language/value/inclusion/location.js +63 -0
  163. package/dist/v1/language/value/inclusion/numbers.d.ts +3 -0
  164. package/dist/v1/language/value/inclusion/numbers.js +41 -0
  165. package/dist/v1/language/value/inclusion/objects.d.ts +3 -0
  166. package/dist/v1/language/value/inclusion/objects.js +190 -0
  167. package/dist/v1/language/value/inclusion/strings.d.ts +3 -0
  168. package/dist/v1/language/value/inclusion/strings.js +29 -0
  169. package/dist/v1/language/value/inclusion/types.d.ts +3 -0
  170. package/dist/v1/language/value/inclusion/types.js +11 -0
  171. package/dist/v1/language/value/ordering.d.ts +14 -0
  172. package/dist/v1/language/value/ordering.js +86 -9
  173. package/dist/v1/language/value/profile/canonicalize.js +6 -5
  174. package/dist/v1/language/value/profile/json.validate.d.ts +3 -1
  175. package/dist/v1/language/value/profile/json.validate.js +3 -2
  176. package/dist/v1/language/value/profile/meta-schema.compiled.js +4 -1
  177. package/dist/v1/language/value/profile/rules.js +17 -43
  178. package/dist/v1/language/value/profile/validate.js +1 -10
  179. package/dist/v1/language/value/profile/vocabulary.d.ts +35 -2
  180. package/dist/v1/language/value/profile/vocabulary.js +52 -5
  181. package/dist/v1/language/value/reference/closure.js +3 -4
  182. package/dist/v1/language/value/reference/recursion.js +2 -22
  183. package/dist/v1/language/value/reference/registry.index.d.ts +2 -0
  184. package/dist/v1/language/value/reference/registry.index.js +33 -16
  185. package/dist/v1/language/value/regexp/ast.js +6 -7
  186. package/dist/v1/language/value/regexp/compile.d.ts +5 -11
  187. package/dist/v1/language/value/regexp/compile.js +14 -12
  188. package/dist/v1/language/value/regexp/syntax.js +3 -2
  189. package/dist/v1/language/value/syntax/keywords.d.ts +3 -3
  190. package/dist/v1/language/value/syntax/keywords.js +4 -20
  191. package/dist/v1/language/value/syntax/node-path/validate.js +2 -3
  192. package/dist/v1/language/value/syntax/pointer.d.ts +2 -0
  193. package/dist/v1/language/value/syntax/pointer.js +5 -2
  194. package/dist/v1/language/value/syntax/walk.d.ts +2 -0
  195. package/dist/v1/language/value/syntax/walk.js +19 -20
  196. package/dist/v1/schema/.spec/schemas/domain-schema.schema.json +2519 -0
  197. package/dist/v1/schema/admission/accept.js +3 -14
  198. package/dist/v1/schema/admission/callable.d.ts +21 -0
  199. package/dist/v1/schema/admission/callable.js +96 -0
  200. package/dist/v1/schema/analysis/class.js +33 -15
  201. package/dist/v1/schema/canonical/revision.js +4 -4
  202. package/dist/v1/schema/compatibility/api.d.ts +2 -1
  203. package/dist/v1/schema/compatibility/api.js +1 -0
  204. package/dist/v1/schema/compatibility/comparators/callables.js +1 -1
  205. package/dist/v1/schema/compatibility/comparators/classes.d.ts +9 -4
  206. package/dist/v1/schema/compatibility/comparators/classes.js +29 -8
  207. package/dist/v1/schema/compatibility/comparators/index.d.ts +1 -1
  208. package/dist/v1/schema/compatibility/comparators/members.js +1 -1
  209. package/dist/v1/schema/compatibility/comparators/values.js +2 -2
  210. package/dist/v1/schema/compatibility/coordinate.js +3 -3
  211. package/dist/v1/schema/compatibility/diff.js +2 -4
  212. package/dist/v1/schema/compatibility/extension.d.ts +11 -0
  213. package/dist/v1/schema/compatibility/extension.js +22 -0
  214. package/dist/v1/schema/compatibility/fields.d.ts +20 -4
  215. package/dist/v1/schema/compatibility/fields.js +13 -3
  216. package/dist/v1/schema/compatibility/meaning/footprint.js +16 -50
  217. package/dist/v1/schema/compatibility/model.d.ts +17 -5
  218. package/dist/v1/schema/compatibility/report.js +1 -1
  219. package/dist/v1/schema/compatibility/scope.d.ts +2 -0
  220. package/dist/v1/schema/compatibility/scope.js +4 -1
  221. package/dist/v1/schema/compatibility/structure/index.js +6 -4
  222. package/dist/v1/schema/compatibility/structure/requirements.js +57 -58
  223. package/dist/v1/schema/compatibility/versioning/index.js +1 -1
  224. package/dist/v1/schema/compatibility/versioning/surface.d.ts +1 -1
  225. package/dist/v1/schema/compatibility/versioning/surface.js +30 -2
  226. package/dist/v1/schema/compatibility/walk.d.ts +17 -0
  227. package/dist/v1/schema/compatibility/walk.js +41 -0
  228. package/dist/v1/schema/diagnostic.d.ts +17 -3
  229. package/dist/v1/schema/diagnostic.js +14 -11
  230. package/dist/v1/schema/index.d.ts +10 -1
  231. package/dist/v1/schema/index.js +4 -0
  232. package/dist/v1/schema/model/schema.d.ts +20 -1
  233. package/dist/v1/schema/model/schema.js +1 -1
  234. package/dist/v1/schema/normalization/domain.d.ts +2 -0
  235. package/dist/v1/schema/normalization/domain.js +29 -9
  236. package/dist/v1/schema/resolution/closure.js +2 -1
  237. package/dist/v1/schema/resolution/context.js +13 -13
  238. package/dist/v1/schema/resolution/domain.d.ts +5 -0
  239. package/dist/v1/schema/resolution/domain.js +2 -2
  240. package/dist/v1/schema/resolution/origins.js +3 -2
  241. package/dist/v1/schema/rule.d.ts +26 -0
  242. package/dist/v1/schema/rule.js +440 -0
  243. package/dist/v1/schema/validation/callable.d.ts +35 -2
  244. package/dist/v1/schema/validation/callable.js +65 -9
  245. package/dist/v1/schema/validation/class.d.ts +6 -2
  246. package/dist/v1/schema/validation/class.js +127 -104
  247. package/dist/v1/schema/validation/core.js +90 -168
  248. package/dist/v1/schema/validation/domain.js +4 -13
  249. package/dist/v1/schema/validation/domain.json-schema.d.ts +15 -0
  250. package/dist/v1/schema/validation/domain.json-schema.js +197 -0
  251. package/dist/v1/schema/validation/domain.route.d.ts +6 -1
  252. package/dist/v1/schema/validation/domain.route.js +18 -0
  253. package/dist/v1/schema/validation/domain.structure.d.ts +7780 -0
  254. package/dist/v1/schema/validation/domain.structure.js +398 -147
  255. package/dist/v1/schema/validation/json.json-schema.d.ts +40 -0
  256. package/dist/v1/schema/validation/json.json-schema.js +46 -0
  257. package/dist/v1/schema/validation/policy/budgets.d.ts +33 -2
  258. package/dist/v1/schema/validation/policy/budgets.js +87 -121
  259. package/dist/v1/schema/validation/policy/context.d.ts +6 -5
  260. package/dist/v1/schema/validation/policy/context.js +7 -10
  261. package/dist/v1/schema/validation/policy/objects.d.ts +1 -1
  262. package/dist/v1/schema/validation/policy/objects.js +6 -14
  263. package/dist/v1/schema/validation/policy/references.js +11 -27
  264. package/dist/v1/schema/validation/policy/typing.d.ts +3 -18
  265. package/dist/v1/schema/validation/policy/typing.js +22 -356
  266. package/dist/v1/schema/validation/policy/uses.d.ts +40 -3
  267. package/dist/v1/schema/validation/policy/uses.js +66 -89
  268. package/dist/v1/schema/validation/policy/validate.js +5 -5
  269. package/dist/v1/schema/validation/value-api.d.ts +22 -0
  270. package/dist/v1/schema/validation/value-api.js +34 -1
  271. package/dist/v1/schema/validation/value.d.ts +3 -0
  272. package/dist/v1/schema/validation/value.js +9 -17
  273. package/dist/v1/schema/validation/value.json-schema.d.ts +49 -0
  274. package/dist/v1/schema/validation/value.json-schema.js +137 -0
  275. package/dist/v1/schema/validation/view.js +4 -8
  276. package/dist/value/canonical.d.ts +6 -0
  277. package/dist/value/canonical.js +36 -0
  278. package/dist/value/decode.d.ts +7 -0
  279. package/dist/value/decode.js +159 -9
  280. package/dist/value/index.d.ts +1 -1
  281. package/dist/value/json.d.ts +2 -2
  282. package/dist/value/json.js +2 -2
  283. package/dist/value/types.d.ts +6 -0
  284. package/dist/value/unicode.d.ts +2 -1
  285. package/dist/value/unicode.js +2 -0
  286. package/package.json +8 -1
  287. package/dist/v1/builder/lowering/core-properties.d.ts +0 -10
  288. package/dist/v1/builder/lowering/core-properties.js +0 -76
  289. package/dist/v1/compiled/admission/semantics/cardinality.d.ts +0 -5
  290. package/dist/v1/compiled/admission/semantics/cardinality.js +0 -113
  291. package/dist/v1/compiled/admission/semantics/policy/equality.d.ts +0 -8
  292. package/dist/v1/compiled/admission/semantics/policy/equality.js +0 -27
  293. package/dist/v1/compiled/admission/semantics/policy/measure.d.ts +0 -9
  294. package/dist/v1/compiled/admission/semantics/policy/measure.js +0 -81
  295. package/dist/v1/compiled/admission/semantics/policy/variants.d.ts +0 -10
  296. package/dist/v1/compiled/admission/semantics/policy/variants.js +0 -65
  297. package/dist/v1/language/class/index.d.ts +0 -8
  298. package/dist/v1/language/class/index.js +0 -1
  299. package/dist/v1/language/core/index.d.ts +0 -2
  300. package/dist/v1/language/value/index.d.ts +0 -11
  301. package/dist/v1/language/value/index.js +0 -8
  302. package/dist/v1/schema/canonical/domain.d.ts +0 -3
  303. package/dist/v1/schema/canonical/domain.digest.d.ts +0 -3
  304. package/dist/v1/schema/canonical/domain.digest.js +0 -5
  305. package/dist/v1/schema/canonical/domain.js +0 -5
  306. package/dist/v1/schema/canonical/freeze.d.ts +0 -1
  307. /package/dist/v1/{language/core/index.js → builder/class/input.js} +0 -0
@@ -1,17 +1,15 @@
1
1
  import { accept as acceptJsonValue, BoundaryError as JsonBoundaryError, json, } from '@astrale-os/kernel-dsl/value';
2
- import { dependencyLimits } from '../addressing/domain-dependency.js';
3
2
  import { compareUnicode } from '../addressing/ordering.js';
3
+ import { limits } from '../language/limits.js';
4
+ import { escapePointerToken } from '../language/value/syntax/pointer.js';
4
5
  import { acceptDomainSchema } from '../schema/admission/accept.js';
5
6
  import { canonicalDomainSchemaAfterValidation } from '../schema/canonical/revision.js';
6
7
  import { revisionOfDomainSchema } from '../schema/canonical/revision.js';
7
8
  import { MemoryDomainSchemaLookup } from '../schema/dependency/lookup.js';
8
9
  import { SchemaError } from '../schema/diagnostic.js';
9
- import { BundleError, diagnostic } from './diagnostic.js';
10
+ import { BundleError, diagnostic, schemaDiagnosticAt } from './diagnostic.js';
10
11
  import { asDomainSchemaBundle, } from './model.js';
11
12
  import { parseDomainSchemaBundleStructure } from './structure.js';
12
- function escapeToken(value) {
13
- return value.replaceAll('~', '~0').replaceAll('/', '~1');
14
- }
15
13
  export function acceptDomainSchemaBundle(input) {
16
14
  let admitted;
17
15
  try {
@@ -48,12 +46,12 @@ function acceptBundleValue(input) {
48
46
  const closure = structure.closure.map((schema, index) => candidate(schema, `/closure/${index}`));
49
47
  const diagnostics = [];
50
48
  const candidates = new Map();
51
- if (closure.length + 1 > dependencyLimits.closure) {
52
- diagnostics.push(diagnostic('DV_DEPENDENCY_LIMITS', '/closure', `A dependency closure may contain at most ${dependencyLimits.closure} Domains.`));
49
+ if (closure.length + 1 > limits.dependency.closure) {
50
+ diagnostics.push(diagnostic('DV_DEPENDENCY_LIMITS', '/closure', `A dependency closure may contain at most ${limits.dependency.closure} Domains.`));
53
51
  }
54
52
  for (const entry of [root, ...closure]) {
55
- if (Object.keys(entry.schema.dependencies).length > dependencyLimits.direct) {
56
- diagnostics.push(diagnostic('DV_DEPENDENCY_LIMITS', `${entry.pointer}/dependencies`, `A Domain may declare at most ${dependencyLimits.direct} direct dependency aliases.`));
53
+ if (Object.keys(entry.schema.dependencies).length > limits.dependency.direct) {
54
+ diagnostics.push(diagnostic('DV_DEPENDENCY_LIMITS', `${entry.pointer}/dependencies`, `A Domain may declare at most ${limits.dependency.direct} direct dependency aliases.`));
57
55
  }
58
56
  }
59
57
  for (const entry of closure) {
@@ -101,7 +99,7 @@ function acceptBundleValue(input) {
101
99
  catch (error) {
102
100
  if (!(error instanceof SchemaError))
103
101
  throw error;
104
- throw new BundleError(error.diagnostics.map((item) => diagnostic(item.code, `${entry.pointer}${item.pointer}`, item.message, item.ref)));
102
+ throw new BundleError(error.diagnostics.map((item) => schemaDiagnosticAt(entry.pointer, item)));
105
103
  }
106
104
  };
107
105
  for (const entry of candidates.values()) {
@@ -130,13 +128,13 @@ function collectReachable(current, root, candidates, reachable, active, revision
130
128
  return;
131
129
  }
132
130
  active.add(current.key);
133
- if (depth > dependencyLimits.depth) {
134
- diagnostics.push(diagnostic('DV_DEPENDENCY_LIMITS', current.pointer, `Dependency depth ${depth} exceeds the maximum ${dependencyLimits.depth}.`));
131
+ if (depth > limits.dependency.depth) {
132
+ diagnostics.push(diagnostic('DV_DEPENDENCY_LIMITS', current.pointer, `Dependency depth ${depth} exceeds the maximum ${limits.dependency.depth}.`));
135
133
  active.delete(current.key);
136
134
  return;
137
135
  }
138
136
  for (const [alias, dependency] of Object.entries(current.schema.dependencies)) {
139
- const pointer = `${current.pointer}/dependencies/${escapeToken(alias)}`;
137
+ const pointer = `${current.pointer}/dependencies/${escapePointerToken(alias)}`;
140
138
  const dependencyKey = keyOf(dependency.origin, dependency.revision);
141
139
  if (dependencyKey === root.key) {
142
140
  diagnostics.push(diagnostic('BUNDLE_CLOSURE_CYCLE', pointer, 'Bundle dependency closure returns to its root.'));
@@ -4,6 +4,8 @@ export type BundleDiagnostic<Code extends BundleDiagnosticCode = BundleDiagnosti
4
4
  readonly code: Code;
5
5
  };
6
6
  export declare function diagnostic<const Code extends BundleDiagnosticCode>(code: Code, pointer: string, message: string, ref?: string): BundleDiagnostic<Code>;
7
+ /** A refusal of one bundled schema, its pointer rebased under the schema's place in the bundle. */
8
+ export declare function schemaDiagnosticAt(pointer: string, refusal: SchemaDiagnostic): BundleDiagnostic;
7
9
  export declare class BundleError extends Error {
8
10
  readonly diagnostics: readonly BundleDiagnostic[];
9
11
  constructor(diagnostics: readonly BundleDiagnostic[]);
@@ -1,16 +1,18 @@
1
- import { compareUnicode } from '../addressing/ordering.js';
1
+ import { formatDiagnostics, orderDiagnostics } from '../language/validation/diagnostic.js';
2
2
  export function diagnostic(code, pointer, message, ref) {
3
3
  return Object.freeze({ code, pointer, message, ...(ref === undefined ? {} : { ref }) });
4
4
  }
5
+ /** A refusal of one bundled schema, its pointer rebased under the schema's place in the bundle. */
6
+ export function schemaDiagnosticAt(pointer, refusal) {
7
+ // Acceptance refuses a document with Schema codes only, never with comparison request codes.
8
+ const code = refusal.code;
9
+ return Object.freeze({ ...refusal, code, pointer: `${pointer}${refusal.pointer}` });
10
+ }
5
11
  export class BundleError extends Error {
6
12
  diagnostics;
7
13
  constructor(diagnostics) {
8
- const ordered = [...diagnostics].sort((left, right) => compareUnicode(left.pointer, right.pointer) ||
9
- compareUnicode(left.code, right.code) ||
10
- compareUnicode(left.message, right.message));
11
- super(ordered
12
- .map(({ code, pointer, message }) => `${pointer || '/'} [${code}] ${message}`)
13
- .join('\n'));
14
+ const ordered = orderDiagnostics(diagnostics);
15
+ super(formatDiagnostics(ordered));
14
16
  this.name = 'BundleError';
15
17
  this.diagnostics = Object.freeze(ordered);
16
18
  }
@@ -1,4 +1,4 @@
1
- import { deepFreeze } from '../schema/canonical/freeze.js';
1
+ import { deepFreeze } from '../language/freeze.js';
2
2
  export const DOMAIN_BUNDLE_FORMAT = 'astrale.dsl.bundle';
3
3
  export const DOMAIN_BUNDLE_VERSION = 'v1';
4
4
  export function asDomainSchemaBundle(root, closure) {
@@ -1,6 +1,7 @@
1
+ import { escapePointerToken } from '../language/value/syntax/pointer.js';
1
2
  import { SchemaError } from '../schema/diagnostic.js';
2
3
  import { routeDomainSchema } from '../schema/validation/domain.route.js';
3
- import { BundleError, diagnostic } from './diagnostic.js';
4
+ import { BundleError, diagnostic, schemaDiagnosticAt } from './diagnostic.js';
4
5
  import { DOMAIN_BUNDLE_FORMAT, DOMAIN_BUNDLE_VERSION } from './model.js';
5
6
  export function parseDomainSchemaBundleStructure(input) {
6
7
  if (!isObject(input)) {
@@ -12,7 +13,7 @@ export function parseDomainSchemaBundleStructure(input) {
12
13
  const expected = new Set(['format', 'version', 'root', 'closure']);
13
14
  for (const key of Object.keys(input)) {
14
15
  if (!expected.has(key)) {
15
- diagnostics.push(diagnostic('BUNDLE_STRUCTURE', `/${escapeToken(key)}`, `Unknown bundle field ${key}.`));
16
+ diagnostics.push(diagnostic('BUNDLE_STRUCTURE', `/${escapePointerToken(key)}`, `Unknown bundle field ${key}.`));
16
17
  }
17
18
  }
18
19
  for (const key of expected) {
@@ -56,7 +57,7 @@ function routeAt(value, pointer, diagnostics) {
56
57
  catch (error) {
57
58
  if (!(error instanceof SchemaError))
58
59
  throw error;
59
- diagnostics.push(...error.diagnostics.map((entry) => diagnostic(entry.code, `${pointer}${entry.pointer}`, entry.message, entry.ref)));
60
+ diagnostics.push(...error.diagnostics.map((entry) => schemaDiagnosticAt(pointer, entry)));
60
61
  return undefined;
61
62
  }
62
63
  }
@@ -66,6 +67,3 @@ function isObject(value) {
66
67
  function describe(value) {
67
68
  return value === undefined ? '(missing)' : JSON.stringify(value);
68
69
  }
69
- function escapeToken(value) {
70
- return value.replaceAll('~', '~0').replaceAll('/', '~1');
71
- }
@@ -1,5 +1,6 @@
1
1
  import { accept as acceptPortable } from '@astrale-os/kernel-dsl/value';
2
- import { dependencyLimits } from '../../addressing/domain-dependency.js';
2
+ import { deepFreeze } from '../../language/freeze.js';
3
+ import { limits } from '../../language/limits.js';
3
4
  import {} from '../model/schema.js';
4
5
  import { validateClosure } from './closure.js';
5
6
  import { invalid, pointer } from './diagnostic.js';
@@ -20,7 +21,7 @@ export function acceptCompiledSchema(input) {
20
21
  const rootPin = dependency(root.root, 'root', '/root');
21
22
  const machines = new Map();
22
23
  const closure = array(root.closure, 'closure', '/closure').map((value, index) => entry(value, index, `/closure/${index}`, machines));
23
- if (closure.length > dependencyLimits.closure) {
24
+ if (closure.length > limits.dependency.closure) {
24
25
  invalid('dependency closure limit', 'COMPILED_DEPENDENCY_LIMITS', '/closure');
25
26
  }
26
27
  const closureOrigins = new Set();
@@ -34,7 +35,7 @@ export function acceptCompiledSchema(input) {
34
35
  if (rootEntry?.revision !== rootPin.revision)
35
36
  invalid('root pin', undefined, '/root');
36
37
  for (const [entryIndex, owner] of closure.entries()) {
37
- if (Object.keys(owner.dependencies).length > dependencyLimits.direct) {
38
+ if (Object.keys(owner.dependencies).length > limits.dependency.direct) {
38
39
  invalid('direct dependency limit', 'COMPILED_DEPENDENCY_LIMITS', `/closure/${entryIndex}/dependencies`);
39
40
  }
40
41
  for (const [alias, pin] of Object.entries(owner.dependencies)) {
@@ -69,10 +70,3 @@ export function acceptCompiledSchema(input) {
69
70
  validateCompiledSemantics(candidate);
70
71
  return deepFreeze(candidate);
71
72
  }
72
- function deepFreeze(input) {
73
- if (input === null || typeof input !== 'object' || Object.isFrozen(input))
74
- return input;
75
- for (const value of Object.values(input))
76
- deepFreeze(value);
77
- return Object.freeze(input);
78
- }
@@ -1,7 +1,7 @@
1
1
  import {} from '@astrale-os/kernel-dsl/value';
2
- import { dependencyLimits } from '../../addressing/domain-dependency.js';
3
2
  import { Key, isDefinitionRef } from '../../addressing/index.js';
4
3
  import {} from '../../language/class/model/edge.js';
4
+ import { limits } from '../../language/limits.js';
5
5
  import {} from '../model/schema.js';
6
6
  import { invalid, pointer } from './diagnostic.js';
7
7
  /** Require closed direct references, acyclic inheritance and concrete Core Classes. */
@@ -128,7 +128,7 @@ function validateDependencyCycles(candidate) {
128
128
  const visited = new Set();
129
129
  const frames = [];
130
130
  const push = (origin, depth) => {
131
- if (depth > dependencyLimits.depth) {
131
+ if (depth > limits.dependency.depth) {
132
132
  invalid('dependency depth limit', 'COMPILED_DEPENDENCY_LIMITS', `/closure/${byOrigin.get(origin)?.index ?? 0}/dependencies`);
133
133
  }
134
134
  active.add(origin);
@@ -1,6 +1,6 @@
1
1
  import { type CompiledDiagnosticCode } from '../diagnostic.js';
2
2
  /** Append one escaped JSON Pointer segment. */
3
- export declare function pointer(parent: string, member: string | number): string;
3
+ export { appendPointer as pointer } from '../../language/value/syntax/pointer.js';
4
4
  /** Report a structural compiled-input violation with its stable diagnostic code. */
5
5
  export declare function invalid(label: string, code?: CompiledDiagnosticCode, path?: string): never;
6
6
  /** Report a contextual compiled-language violation at its original source pointer. */
@@ -1,8 +1,6 @@
1
1
  import { invalidCompiled } from '../diagnostic.js';
2
2
  /** Append one escaped JSON Pointer segment. */
3
- export function pointer(parent, member) {
4
- return `${parent}/${String(member).replaceAll('~', '~0').replaceAll('/', '~1')}`;
5
- }
3
+ export { appendPointer as pointer } from '../../language/value/syntax/pointer.js';
6
4
  /** Report a structural compiled-input violation with its stable diagnostic code. */
7
5
  export function invalid(label, code = 'COMPILED_STRUCTURE_INVALID', path = '') {
8
6
  return invalidCompiled(code, `Invalid compiled Schema ${label}.`, path);
@@ -1,4 +1,12 @@
1
1
  import type { Revision } from '../../addressing/index.js';
2
- import type { CompiledSchemaEntry } from '../model/schema.js';
2
+ import type { FunctionDefinition, MethodDefinition } from '../../language/callable/model/callable.js';
3
+ import type { JsonSchema } from '../../language/value/model/schema.js';
4
+ import type { CompiledFunction, CompiledMethod, CompiledSchemaEntry } from '../model/schema.js';
3
5
  /** Derive the exact canonical source-revision preimage without constructing an authored Schema. */
4
6
  export declare function revisionOfCompiledEntry(entry: CompiledSchemaEntry): Revision;
7
+ /** The source definition of a compiled Method: its value programs back to their schemas. */
8
+ export declare function sourceMethod(entry: CompiledSchemaEntry, method: CompiledMethod): MethodDefinition;
9
+ /** The source definition of a compiled Function: its value programs back to their schemas. */
10
+ export declare function sourceFunction(entry: CompiledSchemaEntry, definition: CompiledFunction): FunctionDefinition;
11
+ /** The schema of the root node of the entry's value program `index`. */
12
+ export declare function schemaOf(entry: CompiledSchemaEntry, index: number): JsonSchema;
@@ -44,7 +44,8 @@ function sourceClass(entry, definition) {
44
44
  methods: Object.fromEntries(methods.map((method) => [method.name, sourceMethod(entry, method)])),
45
45
  };
46
46
  }
47
- function sourceMethod(entry, method) {
47
+ /** The source definition of a compiled Method: its value programs back to their schemas. */
48
+ export function sourceMethod(entry, method) {
48
49
  const { name: _, input, fields: __, output, ...rest } = method;
49
50
  return {
50
51
  ...rest,
@@ -52,7 +53,8 @@ function sourceMethod(entry, method) {
52
53
  output: sourceOutput(entry, output),
53
54
  };
54
55
  }
55
- function sourceFunction(entry, definition) {
56
+ /** The source definition of a compiled Function: its value programs back to their schemas. */
57
+ export function sourceFunction(entry, definition) {
56
58
  const { input, fields: _, output, ...rest } = definition;
57
59
  return {
58
60
  ...rest,
@@ -72,7 +74,8 @@ function sourceOutput(entry, output) {
72
74
  const schema = schemaOf(entry, output.value);
73
75
  return output.mode === 'value' ? { mode: 'value', schema } : { mode: 'stream', item: schema };
74
76
  }
75
- function schemaOf(entry, index) {
77
+ /** The schema of the root node of the entry's value program `index`. */
78
+ export function schemaOf(entry, index) {
76
79
  const program = entry.values[index];
77
80
  const root = program?.nodes[program.root];
78
81
  if (root === undefined)
@@ -1,5 +1,8 @@
1
1
  import { type Located, type CompiledClass, type ClassAnalysis, type SemanticIndex } from './context.js';
2
- /** Compose inherited Properties, Methods and Data ownership once per Class. */
2
+ /**
3
+ * Compose inherited Properties, Methods and Data ownership once per Class. The closure check has
4
+ * already proved every parent present and the inheritance graph acyclic.
5
+ */
3
6
  export declare function analyzeClasses(classes: ReadonlyMap<string, Located<CompiledClass>>): ReadonlyMap<string, ClassAnalysis>;
4
7
  /** Check automatic Properties, immutability and abstract Class obligations. */
5
8
  export declare function validateClassFacets(context: SemanticIndex): void;
@@ -2,26 +2,26 @@ import { json } from '@astrale-os/kernel-dsl/value';
2
2
  import { Key, PropertyKey as PropertyKeyValue, } from '../../../addressing/index.js';
3
3
  import { composeMethods } from '../../../language/callable/composition.js';
4
4
  import { isMethodExecutable } from '../../../language/callable/executable.js';
5
+ import { keyableProperty } from '../../../language/class/unique.js';
5
6
  import { bindValueProgram } from '../../../language/value/compile/load.js';
6
7
  import {} from '../../model/schema.js';
7
8
  import { fail } from '../diagnostic.js';
8
9
  import {} from './context.js';
9
- /** Compose inherited Properties, Methods and Data ownership once per Class. */
10
+ /**
11
+ * Compose inherited Properties, Methods and Data ownership once per Class. The closure check has
12
+ * already proved every parent present and the inheritance graph acyclic.
13
+ */
10
14
  export function analyzeClasses(classes) {
11
15
  const analyses = new Map();
12
- const visiting = new Set();
13
16
  const analyze = (located) => {
14
17
  const classKey = Key.of(located.value.ref);
15
18
  const cached = analyses.get(classKey);
16
19
  if (cached !== undefined)
17
20
  return cached;
18
- if (visiting.has(classKey))
19
- fail(`${located.pointer}/extends`, 'Class inheritance is cyclic.');
20
- visiting.add(classKey);
21
21
  const parents = located.value.extends.map((ref, index) => {
22
22
  const parent = classes.get(Key.of(ref));
23
- if (parent === undefined)
24
- fail(`${located.pointer}/extends/${index}`, 'Parent Class is absent.');
23
+ if (parent.value.inheritance === 'final')
24
+ fail(`${located.pointer}/extends/${index}`, 'A final Class has no subclass.');
25
25
  return analyze(parent);
26
26
  });
27
27
  const properties = new Map();
@@ -68,7 +68,6 @@ export function analyzeClasses(classes) {
68
68
  ...(dataOwner === undefined ? {} : { dataOwner }),
69
69
  };
70
70
  analyses.set(classKey, analysis);
71
- visiting.delete(classKey);
72
71
  return analysis;
73
72
  };
74
73
  for (const value of classes.values())
@@ -91,9 +90,8 @@ function programKey(entry, value) {
91
90
  /** Check automatic Properties, immutability and abstract Class obligations. */
92
91
  export function validateClassFacets(context) {
93
92
  for (const located of context.classes.values()) {
94
- if (located.value.abstract &&
95
- (located.value.policies.read !== undefined || located.value.policies.traverse !== undefined)) {
96
- fail(`${located.pointer}/policies`, 'Abstract Classes cannot declare observation Policies.');
93
+ if (located.value.abstract && Object.keys(located.value.policies).length > 0) {
94
+ fail(`${located.pointer}/policies`, 'Abstract Classes cannot declare Class Policies.');
97
95
  }
98
96
  for (const [index, property] of located.value.properties.entries()) {
99
97
  const path = `${located.pointer}/properties/${index}`;
@@ -114,11 +112,38 @@ export function validateClassFacets(context) {
114
112
  }
115
113
  }
116
114
  }
115
+ if (located.value.unique !== undefined) {
116
+ const properties = context.analyses.get(Key.of(located.value.ref))?.properties;
117
+ const keyable = (key, at) => {
118
+ const property = properties?.get(key)?.declaration;
119
+ if (property === undefined || !keyableProperty(property.ordering, property.auto)) {
120
+ fail(at, 'A key Property is a keyable Property of the Class.');
121
+ }
122
+ };
123
+ // A Node tuple names Properties only; an Edge tuple names them as `{ property }`.
124
+ const value = located.value;
125
+ if (value.kind === 'node') {
126
+ for (const [t, tuple] of (value.unique ?? []).entries())
127
+ for (const [f, key] of tuple.entries())
128
+ keyable(key, `${located.pointer}/unique/${t}/${f}`);
129
+ }
130
+ else {
131
+ for (const [t, tuple] of (value.unique ?? []).entries())
132
+ for (const [f, field] of tuple.entries())
133
+ if (typeof field !== 'string')
134
+ keyable(field.property, `${located.pointer}/unique/${t}/${f}/property`);
135
+ }
136
+ }
117
137
  if (located.value.kind === 'node') {
118
138
  for (const [index, method] of located.value.methods.entries()) {
119
- if (!isMethodExecutable(located.value, method) && method.policy !== undefined) {
139
+ if (isMethodExecutable(located.value, method))
140
+ continue;
141
+ if (method.policy !== undefined) {
120
142
  fail(`${located.pointer}/methods/${index}/policy`, 'An abstract Method cannot have a Policy.');
121
143
  }
144
+ if (method.admission !== undefined) {
145
+ fail(`${located.pointer}/methods/${index}/admission`, 'An abstract Method cannot have an admission age.');
146
+ }
122
147
  }
123
148
  }
124
149
  }
@@ -1,7 +1,5 @@
1
- import { type ClassRef } from '../../../addressing/index.js';
2
- import { type CoreEdge } from '../../../language/core/model/core.js';
3
1
  import { type CompiledSchemaEntry, type CompiledSchema } from '../../model/schema.js';
4
- import { type Located, type CompiledClass, type ClassAnalysis, type CompiledEdge, type SemanticIndex } from './context.js';
2
+ import { type Located, type CompiledClass, type ClassAnalysis, type SemanticIndex } from './context.js';
5
3
  /** A local Core Node paired with its admitted Class analysis. */
6
4
  export interface CoreNode {
7
5
  readonly key: string;
@@ -10,26 +8,5 @@ export interface CoreNode {
10
8
  readonly analysis: ClassAnalysis;
11
9
  readonly pointer: string;
12
10
  }
13
- /**
14
- * A local Definition other than a Core Node, or a Class-owned Method. The Domain projects it as a
15
- * Kernel declaration Node, so `class` names that Kernel Class rather than an authored one.
16
- */
17
- interface CoreMemberEndpoint {
18
- readonly key: string;
19
- readonly class: ClassRef;
20
- readonly pointer: string;
21
- }
22
- type CoreEndpoint = CoreNode | CoreMemberEndpoint | {
23
- readonly key: 'domain';
24
- };
25
- /** A Core Edge paired with resolved endpoints and its exact Class. */
26
- export interface CoreEdgeValue {
27
- readonly source: CoreEndpoint;
28
- readonly target: CoreEndpoint;
29
- readonly value: CoreEdge;
30
- readonly class: Located<CompiledEdge>;
31
- readonly pointer: string;
32
- }
33
11
  /** Admit local Core Nodes, Properties and Edge endpoint contracts. */
34
12
  export declare function validateCore(candidate: CompiledSchema, context: SemanticIndex): void;
35
- export {};
@@ -1,15 +1,19 @@
1
1
  import { Key } from '../../../addressing/index.js';
2
2
  import { isMethodExecutable } from '../../../language/callable/executable.js';
3
+ import { coveringEdgeUniqueTuples, coveringNodeUniqueTuples, edgeUniqueKeys, nodeUniqueKeys, } from '../../../language/class/unique.js';
4
+ import { checkCoreEdgeSet, checkHeldKeys, coreEndpointsSatisfy, DOMAIN_ENDPOINT_CLASS, } from '../../../language/core/facts.js';
3
5
  import {} from '../../../language/core/model/core.js';
4
6
  import { policyObjectOrigin, policyObjectKey, projectedMemberClass, } from '../../../language/index.js';
5
7
  import { bindValueProgram } from '../../../language/value/compile/load.js';
6
8
  import { validateValueProgram } from '../../../language/value/evaluate/program.js';
9
+ import { escapePointerToken } from '../../../language/value/syntax/pointer.js';
7
10
  import {} from '../../model/schema.js';
8
11
  import { fail } from '../diagnostic.js';
9
- import { validateCoreEdgeSet } from './cardinality.js';
10
12
  import { isCompiledEdge, classSatisfiesAny, } from './context.js';
13
+ import { sameIncidentEndpoint } from './edge.js';
11
14
  /** Admit local Core Nodes, Properties and Edge endpoint contracts. */
12
15
  export function validateCore(candidate, context) {
16
+ const resolve = (ref) => context.classes.get(Key.of(ref))?.value;
13
17
  for (const [entryIndex, entry] of candidate.closure.entries()) {
14
18
  const nodes = new Map();
15
19
  for (const [index, value] of entry.definitions.core.entries()) {
@@ -31,6 +35,9 @@ export function validateCore(candidate, context) {
31
35
  pointer: path,
32
36
  });
33
37
  }
38
+ checkHeldKeys(nodes.values(), (node) => nodeUniqueKeys(coveringNodeUniqueTuples(node.class.value, resolve), {
39
+ props: node.value.properties,
40
+ }), (node) => fail(node.pointer, 'Core Node holds a key another Core Node holds.'));
34
41
  const edges = [];
35
42
  for (const [index, value] of entry.facts.core.entries()) {
36
43
  const path = `/closure/${entryIndex}/facts/core/${index}`;
@@ -46,14 +53,7 @@ export function validateCore(candidate, context) {
46
53
  validateCoreProperties(value.properties, analysis, `${path}/properties`);
47
54
  const source = resolveCoreEndpoint(context, entry, value.source, nodes, `${path}/source`);
48
55
  const target = resolveCoreEndpoint(context, entry, value.target, nodes, `${path}/target`);
49
- const declaration = classValue.value;
50
- const satisfies = declaration.orientation === 'directed'
51
- ? endpointSatisfies(context, source, declaration.endpoints.source.accepts) &&
52
- endpointSatisfies(context, target, declaration.endpoints.target.accepts)
53
- : (endpointSatisfies(context, source, declaration.endpoints[0].accepts) &&
54
- endpointSatisfies(context, target, declaration.endpoints[1].accepts)) ||
55
- (endpointSatisfies(context, source, declaration.endpoints[1].accepts) &&
56
- endpointSatisfies(context, target, declaration.endpoints[0].accepts));
56
+ const satisfies = coreEndpointsSatisfy(classValue.value, source, target, (endpoint, accepts) => endpointSatisfies(context, endpoint, accepts));
57
57
  if (!satisfies)
58
58
  fail(path, 'Core Edge endpoints do not satisfy its exact Class.');
59
59
  edges.push({
@@ -64,28 +64,66 @@ export function validateCore(candidate, context) {
64
64
  pointer: path,
65
65
  });
66
66
  }
67
- validateCoreEdgeSet(context, entry, entryIndex, nodes, edges);
67
+ checkCoreEdgeSet({
68
+ edges: edges.map((edge) => ({
69
+ edge,
70
+ class: Key.of(edge.value.class),
71
+ contract: edge.class.value,
72
+ source: edge.source,
73
+ target: edge.target,
74
+ })),
75
+ classes: entry.definitions.classes
76
+ .filter(isCompiledEdge)
77
+ .map((value) => ({ key: Key.of(value.ref), contract: value })),
78
+ nodes: [...nodes.values()].map(({ key, value, pointer }) => ({
79
+ key,
80
+ class: value.class,
81
+ pointer,
82
+ })),
83
+ satisfies: (ref, accepts) => classSatisfiesAny(context, ref, accepts),
84
+ keys: ({ edge }) => edgeUniqueKeys(coveringEdgeUniqueTuples(edge.class.value, resolve), {
85
+ source: edge.source.key,
86
+ target: edge.target.key,
87
+ props: edge.value.properties,
88
+ }),
89
+ sameIncident: sameIncidentEndpoint,
90
+ report: (issue) => coreEdgeFailure(issue, entryIndex),
91
+ });
92
+ }
93
+ }
94
+ function coreEdgeFailure(issue, entryIndex) {
95
+ switch (issue.kind) {
96
+ case 'identity':
97
+ return fail(issue.edge.pointer, 'Core Edge duplicates an exact normalized Edge identity.');
98
+ case 'no-self':
99
+ return fail(issue.edge.pointer, 'Core Edge violates noSelf.');
100
+ case 'key':
101
+ return fail(issue.edge.pointer, 'Core Edge holds a key another Core Edge holds.');
102
+ case 'acyclic':
103
+ return fail(`/closure/${entryIndex}/facts/core`, 'Core Edge set violates exact-Class acyclicity.');
104
+ case 'degree':
105
+ return fail(issue.pointer, `Core degree ${issue.degree} violates Edge count ${issue.count}.`);
68
106
  }
69
107
  }
70
108
  function validateCoreProperties(values, analysis, path) {
71
109
  for (const key of Object.keys(values))
72
110
  if (!analysis.properties.has(key))
73
- fail(`${path}/${escapePointer(key)}`, 'Core properties contain an unknown Property key.');
111
+ fail(`${path}/${escapePointerToken(key)}`, 'Core properties contain an unknown Property key.');
74
112
  for (const property of analysis.properties.values()) {
75
113
  if (!Object.hasOwn(values, property.key)) {
76
114
  if (property.declaration.required && property.declaration.auto === undefined)
77
- fail(`${path}/${escapePointer(property.key)}`, 'Core properties omit a required Property.');
115
+ fail(`${path}/${escapePointerToken(property.key)}`, 'Core properties omit a required Property.');
78
116
  continue;
79
117
  }
80
118
  if (property.declaration.auto !== undefined)
81
- fail(`${path}/${escapePointer(property.key)}`, 'Core properties cannot author an automatic Property.');
119
+ fail(`${path}/${escapePointerToken(property.key)}`, 'Core properties cannot author an automatic Property.');
82
120
  if (validateValueProgram(bindValueProgram(property.entry.values[property.declaration.value], property.entry.patterns), values[property.key]).length > 0)
83
- fail(`${path}/${escapePointer(property.key)}`, 'Core Property value does not satisfy its exact contract.');
121
+ fail(`${path}/${escapePointerToken(property.key)}`, 'Core Property value does not satisfy its exact contract.');
84
122
  }
85
123
  }
86
124
  function resolveCoreEndpoint(context, entry, ref, nodes, path) {
87
125
  if (ref.kind === 'domain')
88
- return { key: 'domain' };
126
+ return { key: 'domain', member: { class: DOMAIN_ENDPOINT_CLASS, pointer: path } };
89
127
  const undeclared = () => fail(path, 'Core endpoint does not name a declared local Definition.');
90
128
  if (policyObjectOrigin(ref) !== entry.origin)
91
129
  return undeclared();
@@ -93,7 +131,8 @@ function resolveCoreEndpoint(context, entry, ref, nodes, path) {
93
131
  return nodes.get(Key.of(ref)) ?? undeclared();
94
132
  if (!declaresProjectedMember(context, entry, ref))
95
133
  return undeclared();
96
- return { key: policyObjectKey(ref), class: projectedMemberClass(ref), pointer: path };
134
+ // A projected member's degree is reported at the endpoint that names it.
135
+ return { key: policyObjectKey(ref), member: { class: projectedMemberClass(ref), pointer: path } };
97
136
  }
98
137
  /** Only a projected declaration can carry a Core fact; an abstract Method is never projected. */
99
138
  function declaresProjectedMember(context, entry, ref) {
@@ -112,12 +151,5 @@ function declaresProjectedMember(context, entry, ref) {
112
151
  return declarations.some((declaration) => declaration.ref.name === ref.name);
113
152
  }
114
153
  function endpointSatisfies(context, endpoint, accepts) {
115
- if ('value' in endpoint)
116
- return classSatisfiesAny(context, endpoint.value.class, accepts);
117
- if ('class' in endpoint)
118
- return classSatisfiesAny(context, endpoint.class, accepts);
119
- return true;
120
- }
121
- function escapePointer(value) {
122
- return value.replaceAll('~', '~0').replaceAll('/', '~1');
154
+ return classSatisfiesAny(context, 'value' in endpoint ? endpoint.value.class : endpoint.member.class, accepts);
123
155
  }
@@ -1,8 +1,6 @@
1
- import { type EdgeCount, type IncidentEndpoint } from '../../../language/class/model/edge.js';
1
+ import { type IncidentEndpoint } from '../../../language/class/model/edge.js';
2
2
  import { type SemanticIndex } from './context.js';
3
- /** Check Edge endpoint contracts and safe inheritance refinement. */
3
+ /** Check safe Edge inheritance refinement; the wire and closure checks own the endpoints. */
4
4
  export declare function validateEdges(context: SemanticIndex): void;
5
5
  /** Compare undirected endpoint acceptance and cardinality contracts. */
6
6
  export declare function sameIncidentEndpoint(left: IncidentEndpoint, right: IncidentEndpoint): boolean;
7
- /** Interpret an Edge count as inclusive degree bounds. */
8
- export declare function countBounds(value: EdgeCount): readonly [number, number];