@astrale-os/kernel-dsl 0.2.0-beta.8 → 0.2.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 (321) hide show
  1. package/dist/v1/addressing/class-key.js +5 -4
  2. package/dist/v1/addressing/method-key.js +3 -2
  3. package/dist/v1/addressing/patterns.d.ts +0 -5
  4. package/dist/v1/addressing/patterns.js +5 -5
  5. package/dist/v1/builder/callable/authoring.d.ts +87 -41
  6. package/dist/v1/builder/callable/authoring.js +29 -14
  7. package/dist/v1/builder/class/authoring.d.ts +311 -36
  8. package/dist/v1/builder/class/authoring.js +3 -4
  9. package/dist/v1/builder/class/property.d.ts +16 -8
  10. package/dist/v1/builder/class/property.js +21 -5
  11. package/dist/v1/builder/core/authoring.d.ts +28 -13
  12. package/dist/v1/builder/core/authoring.js +22 -2
  13. package/dist/v1/builder/index.d.ts +9 -8
  14. package/dist/v1/builder/index.js +2 -2
  15. package/dist/v1/builder/lowering/callable.d.ts +3 -1
  16. package/dist/v1/builder/lowering/callable.js +43 -51
  17. package/dist/v1/builder/lowering/class.d.ts +7 -0
  18. package/dist/v1/builder/lowering/class.js +79 -29
  19. package/dist/v1/builder/lowering/core.d.ts +3 -2
  20. package/dist/v1/builder/lowering/core.js +9 -6
  21. package/dist/v1/builder/lowering/policy.d.ts +8 -1
  22. package/dist/v1/builder/lowering/policy.js +35 -0
  23. package/dist/v1/builder/lowering/schema/capture.js +9 -4
  24. package/dist/v1/builder/lowering/schema/compile.d.ts +2 -2
  25. package/dist/v1/builder/lowering/schema/compile.js +15 -2
  26. package/dist/v1/builder/lowering/schema/context.d.ts +11 -8
  27. package/dist/v1/builder/lowering/schema/context.js +59 -29
  28. package/dist/v1/builder/lowering/schema/ownership.d.ts +3 -3
  29. package/dist/v1/builder/lowering/schema/ownership.js +2 -1
  30. package/dist/v1/builder/lowering/value/compile.js +14 -4
  31. package/dist/v1/builder/lowering/value/zod.d.ts +7 -6
  32. package/dist/v1/builder/lowering/value/zod.js +16 -7
  33. package/dist/v1/builder/lowering/view.d.ts +4 -3
  34. package/dist/v1/builder/lowering/view.js +2 -14
  35. package/dist/v1/builder/policy/authoring.d.ts +23 -6
  36. package/dist/v1/builder/policy/authoring.js +35 -8
  37. package/dist/v1/builder/schema/define.d.ts +8 -5
  38. package/dist/v1/builder/schema/diagnostic.d.ts +1 -1
  39. package/dist/v1/builder/schema/handle.d.ts +2 -1
  40. package/dist/v1/builder/schema/input.d.ts +9 -1
  41. package/dist/v1/builder/schema/projection/callable.d.ts +51 -0
  42. package/dist/v1/builder/schema/projection/callable.js +1 -0
  43. package/dist/v1/builder/schema/projection/class.d.ts +89 -0
  44. package/dist/v1/builder/schema/projection/class.js +1 -0
  45. package/dist/v1/builder/schema/projection/core-input.d.ts +32 -0
  46. package/dist/v1/builder/schema/projection/core-input.js +1 -0
  47. package/dist/v1/builder/schema/projection/domain.d.ts +59 -0
  48. package/dist/v1/builder/schema/projection/domain.js +1 -0
  49. package/dist/v1/builder/schema/projection/identity.d.ts +39 -0
  50. package/dist/v1/builder/schema/projection/identity.js +1 -0
  51. package/dist/v1/builder/schema/projection/model.d.ts +59 -0
  52. package/dist/v1/builder/schema/projection/model.js +1 -0
  53. package/dist/v1/builder/schema/projection/property.d.ts +32 -0
  54. package/dist/v1/builder/schema/projection/property.js +1 -0
  55. package/dist/v1/builder/schema/projection/resolved-class.d.ts +76 -0
  56. package/dist/v1/builder/schema/projection/resolved-class.js +1 -0
  57. package/dist/v1/builder/schema/projection.d.ts +4 -258
  58. package/dist/v1/builder/value/full-match.js +6 -3
  59. package/dist/v1/builder/value/path.d.ts +2 -2
  60. package/dist/v1/builder/value/path.js +2 -2
  61. package/dist/v1/builder/view/authoring.d.ts +6 -14
  62. package/dist/v1/builder/view/authoring.js +13 -5
  63. package/dist/v1/bundle/structure.d.ts +2 -1
  64. package/dist/v1/compiled/admission/accept.d.ts +1 -1
  65. package/dist/v1/compiled/admission/accept.js +11 -814
  66. package/dist/v1/compiled/admission/closure.d.ts +3 -0
  67. package/dist/v1/compiled/admission/closure.js +173 -0
  68. package/dist/v1/compiled/admission/diagnostic.d.ts +7 -0
  69. package/dist/v1/compiled/admission/diagnostic.js +13 -0
  70. package/dist/v1/compiled/admission/revision.js +9 -1
  71. package/dist/v1/compiled/admission/semantics/cardinality.d.ts +5 -0
  72. package/dist/v1/compiled/admission/semantics/cardinality.js +113 -0
  73. package/dist/v1/compiled/admission/semantics/class.d.ts +5 -0
  74. package/dist/v1/compiled/admission/semantics/class.js +125 -0
  75. package/dist/v1/compiled/admission/semantics/context.d.ts +60 -0
  76. package/dist/v1/compiled/admission/semantics/context.js +81 -0
  77. package/dist/v1/compiled/admission/semantics/core.d.ts +35 -0
  78. package/dist/v1/compiled/admission/semantics/core.js +123 -0
  79. package/dist/v1/compiled/admission/semantics/edge.d.ts +8 -0
  80. package/dist/v1/compiled/admission/semantics/edge.js +89 -0
  81. package/dist/v1/compiled/admission/semantics/policy/admit.d.ts +4 -0
  82. package/dist/v1/compiled/admission/semantics/policy/admit.js +63 -0
  83. package/dist/v1/compiled/admission/semantics/policy/callable.d.ts +5 -0
  84. package/dist/v1/compiled/admission/semantics/policy/callable.js +72 -0
  85. package/dist/v1/compiled/admission/semantics/policy/contracts.d.ts +24 -0
  86. package/dist/v1/compiled/admission/semantics/policy/contracts.js +45 -0
  87. package/dist/v1/compiled/admission/semantics/policy/equality.d.ts +8 -0
  88. package/dist/v1/compiled/admission/semantics/policy/equality.js +27 -0
  89. package/dist/v1/compiled/admission/semantics/policy/measure.d.ts +9 -0
  90. package/dist/v1/compiled/admission/semantics/policy/measure.js +81 -0
  91. package/dist/v1/compiled/admission/semantics/policy/parity.d.ts +4 -0
  92. package/dist/v1/compiled/admission/semantics/policy/parity.js +139 -0
  93. package/dist/v1/compiled/admission/semantics/policy/pattern.d.ts +8 -0
  94. package/dist/v1/compiled/admission/semantics/policy/pattern.js +78 -0
  95. package/dist/v1/compiled/admission/semantics/policy/typing.d.ts +28 -0
  96. package/dist/v1/compiled/admission/semantics/policy/typing.js +206 -0
  97. package/dist/v1/compiled/admission/semantics/policy/variants.d.ts +10 -0
  98. package/dist/v1/compiled/admission/semantics/policy/variants.js +65 -0
  99. package/dist/v1/compiled/admission/semantics.d.ts +1 -1
  100. package/dist/v1/compiled/admission/semantics.js +8 -1078
  101. package/dist/v1/compiled/admission/wire/callable.d.ts +6 -0
  102. package/dist/v1/compiled/admission/wire/callable.js +90 -0
  103. package/dist/v1/compiled/admission/wire/class.d.ts +4 -0
  104. package/dist/v1/compiled/admission/wire/class.js +133 -0
  105. package/dist/v1/compiled/admission/wire/core.d.ts +5 -0
  106. package/dist/v1/compiled/admission/wire/core.js +32 -0
  107. package/dist/v1/compiled/admission/wire/dependency.d.ts +14 -0
  108. package/dist/v1/compiled/admission/wire/dependency.js +43 -0
  109. package/dist/v1/compiled/admission/wire/entry.d.ts +5 -0
  110. package/dist/v1/compiled/admission/wire/entry.js +100 -0
  111. package/dist/v1/compiled/admission/wire/pattern.d.ts +12 -0
  112. package/dist/v1/compiled/admission/wire/pattern.js +111 -0
  113. package/dist/v1/compiled/admission/wire/policy.d.ts +10 -0
  114. package/dist/v1/compiled/admission/wire/policy.js +189 -0
  115. package/dist/v1/compiled/admission/wire/program.d.ts +4 -0
  116. package/dist/v1/compiled/admission/wire/program.js +52 -0
  117. package/dist/v1/compiled/admission/wire/property.d.ts +4 -0
  118. package/dist/v1/compiled/admission/wire/property.js +74 -0
  119. package/dist/v1/compiled/admission/wire/reference.d.ts +8 -0
  120. package/dist/v1/compiled/admission/wire/reference.js +33 -0
  121. package/dist/v1/compiled/admission/wire/value.d.ts +29 -0
  122. package/dist/v1/compiled/admission/wire/value.js +98 -0
  123. package/dist/v1/compiled/admission/wire/view.d.ts +3 -0
  124. package/dist/v1/compiled/admission/wire/view.js +17 -0
  125. package/dist/v1/compiled/compiler/compile.js +43 -11
  126. package/dist/v1/compiled/generated.d.ts +10 -0
  127. package/dist/v1/compiled/generated.js +15 -0
  128. package/dist/v1/compiled/loader/load.d.ts +5 -0
  129. package/dist/v1/compiled/loader/load.js +18 -4
  130. package/dist/v1/compiled/model/schema.d.ts +16 -7
  131. package/dist/v1/domain/create.js +18 -28
  132. package/dist/v1/domain/model/domain.d.ts +0 -1
  133. package/dist/v1/domain/model/input.d.ts +3 -0
  134. package/dist/v1/domain/projection/classes.js +13 -41
  135. package/dist/v1/domain/validation/create.d.ts +2 -0
  136. package/dist/v1/domain/validation/create.js +12 -0
  137. package/dist/v1/index.d.ts +5 -2
  138. package/dist/v1/index.js +3 -1
  139. package/dist/v1/language/callable/composition.d.ts +27 -0
  140. package/dist/v1/language/callable/composition.js +52 -0
  141. package/dist/v1/language/callable/executable.d.ts +6 -0
  142. package/dist/v1/language/callable/executable.js +4 -0
  143. package/dist/v1/language/callable/model/callable.d.ts +34 -9
  144. package/dist/v1/language/callable/model/callable.js +3 -1
  145. package/dist/v1/language/callable/resolved.d.ts +23 -8
  146. package/dist/v1/language/class/facets.d.ts +5 -2
  147. package/dist/v1/language/class/inheritance.d.ts +12 -0
  148. package/dist/v1/language/class/inheritance.js +25 -0
  149. package/dist/v1/language/class/lifetime.d.ts +17 -0
  150. package/dist/v1/language/class/lifetime.js +26 -0
  151. package/dist/v1/language/class/model/class.d.ts +8 -4
  152. package/dist/v1/language/class/model/property.d.ts +4 -2
  153. package/dist/v1/language/class/property-values.js +5 -2
  154. package/dist/v1/language/class/resolved.d.ts +25 -15
  155. package/dist/v1/language/core/model/core.d.ts +7 -1
  156. package/dist/v1/language/core/resolved.d.ts +6 -2
  157. package/dist/v1/language/definition/metadata.d.ts +8 -0
  158. package/dist/v1/language/definition/metadata.js +12 -0
  159. package/dist/v1/language/index.d.ts +9 -0
  160. package/dist/v1/language/index.js +6 -0
  161. package/dist/v1/language/policy/analysis/branches.d.ts +4 -3
  162. package/dist/v1/language/policy/analysis/branches.js +54 -12
  163. package/dist/v1/language/policy/analysis/budgets.js +1 -1
  164. package/dist/v1/language/policy/analysis/checks.d.ts +28 -0
  165. package/dist/v1/language/policy/analysis/checks.js +80 -0
  166. package/dist/v1/language/policy/index.d.ts +1 -0
  167. package/dist/v1/language/policy/index.js +1 -0
  168. package/dist/v1/language/policy/model/policy.d.ts +71 -5
  169. package/dist/v1/language/policy/model/policy.js +52 -1
  170. package/dist/v1/language/policy/normalization/normalize.d.ts +12 -1
  171. package/dist/v1/language/policy/normalization/normalize.js +178 -44
  172. package/dist/v1/language/state/index.d.ts +3 -0
  173. package/dist/v1/language/state/index.js +1 -0
  174. package/dist/v1/language/state/machine.d.ts +28 -0
  175. package/dist/v1/language/state/machine.js +40 -0
  176. package/dist/v1/language/state/topology.d.ts +14 -0
  177. package/dist/v1/language/state/topology.js +69 -0
  178. package/dist/v1/language/value/compile/fields.d.ts +1 -1
  179. package/dist/v1/language/value/compile/load.d.ts +4 -2
  180. package/dist/v1/language/value/compile/load.js +22 -1
  181. package/dist/v1/language/value/compile/model.d.ts +16 -1
  182. package/dist/v1/language/value/evaluate/assertions.d.ts +2 -0
  183. package/dist/v1/language/value/evaluate/assertions.js +13 -0
  184. package/dist/v1/language/value/evaluate/evaluator.js +111 -28
  185. package/dist/v1/language/value/evaluate/preparation.d.ts +10 -1
  186. package/dist/v1/language/value/evaluate/preparation.js +17 -26
  187. package/dist/v1/language/value/evaluate/program.js +1 -1
  188. package/dist/v1/language/value/evaluate/validate.d.ts +6 -2
  189. package/dist/v1/language/value/evaluate/validate.js +18 -11
  190. package/dist/v1/language/value/inclusion/includes.d.ts +9 -0
  191. package/dist/v1/language/value/inclusion/includes.js +777 -0
  192. package/dist/v1/language/value/model/blob.d.ts +31 -0
  193. package/dist/v1/language/value/model/blob.js +90 -0
  194. package/dist/v1/language/value/model/instant.d.ts +0 -2
  195. package/dist/v1/language/value/model/instant.js +1 -1
  196. package/dist/v1/language/value/model/schema.d.ts +2 -1
  197. package/dist/v1/language/value/model/schema.js +1 -5
  198. package/dist/v1/language/value/ordering.d.ts +2 -0
  199. package/dist/v1/language/value/ordering.js +4 -8
  200. package/dist/v1/language/value/profile/json.validate.js +1 -1
  201. package/dist/v1/language/value/profile/rules.js +48 -12
  202. package/dist/v1/language/value/reference/registry.d.ts +2 -1
  203. package/dist/v1/language/value/regexp/ast.js +3 -64
  204. package/dist/v1/language/value/regexp/compile.d.ts +32 -3
  205. package/dist/v1/language/value/regexp/compile.js +117 -21
  206. package/dist/v1/language/value/regexp/matcher.d.ts +6 -3
  207. package/dist/v1/language/value/regexp/matcher.js +185 -28
  208. package/dist/v1/language/value/regexp/syntax.d.ts +12 -1
  209. package/dist/v1/language/value/regexp/syntax.js +14 -2
  210. package/dist/v1/language/value/regexp/unicode.d.ts +32 -0
  211. package/dist/v1/language/value/regexp/unicode.js +139 -0
  212. package/dist/v1/language/value/syntax/full-match.js +8 -5
  213. package/dist/v1/language/value/syntax/node-path/validate.js +4 -6
  214. package/dist/v1/language/view/model/view.d.ts +2 -4
  215. package/dist/v1/language/view/resolved.d.ts +2 -2
  216. package/dist/v1/schema/analysis/class.d.ts +36 -6
  217. package/dist/v1/schema/analysis/class.js +31 -66
  218. package/dist/v1/schema/canonical/revision.d.ts +2 -1
  219. package/dist/v1/schema/canonical/revision.js +4 -1
  220. package/dist/v1/schema/compatibility/api.d.ts +3 -0
  221. package/dist/v1/schema/compatibility/api.js +2 -0
  222. package/dist/v1/schema/compatibility/comparators/callables.d.ts +39 -0
  223. package/dist/v1/schema/compatibility/comparators/callables.js +101 -0
  224. package/dist/v1/schema/compatibility/comparators/classes.d.ts +47 -0
  225. package/dist/v1/schema/compatibility/comparators/classes.js +160 -0
  226. package/dist/v1/schema/compatibility/comparators/index.d.ts +12 -0
  227. package/dist/v1/schema/compatibility/comparators/index.js +53 -0
  228. package/dist/v1/schema/compatibility/comparators/members.d.ts +4 -0
  229. package/dist/v1/schema/compatibility/comparators/members.js +49 -0
  230. package/dist/v1/schema/compatibility/comparators/values.d.ts +5 -0
  231. package/dist/v1/schema/compatibility/comparators/values.js +37 -0
  232. package/dist/v1/schema/compatibility/compare.d.ts +5 -0
  233. package/dist/v1/schema/compatibility/compare.js +23 -0
  234. package/dist/v1/schema/compatibility/context.d.ts +19 -0
  235. package/dist/v1/schema/compatibility/context.js +49 -0
  236. package/dist/v1/schema/compatibility/coordinate.d.ts +40 -0
  237. package/dist/v1/schema/compatibility/coordinate.js +38 -0
  238. package/dist/v1/schema/compatibility/diff.d.ts +12 -0
  239. package/dist/v1/schema/compatibility/diff.js +39 -0
  240. package/dist/v1/schema/compatibility/evidence.d.ts +16 -0
  241. package/dist/v1/schema/compatibility/evidence.js +62 -0
  242. package/dist/v1/schema/compatibility/fields.d.ts +194 -0
  243. package/dist/v1/schema/compatibility/fields.js +94 -0
  244. package/dist/v1/schema/compatibility/index.d.ts +6 -0
  245. package/dist/v1/schema/compatibility/index.js +3 -0
  246. package/dist/v1/schema/compatibility/meaning/footprint.d.ts +7 -0
  247. package/dist/v1/schema/compatibility/meaning/footprint.js +59 -0
  248. package/dist/v1/schema/compatibility/meaning/index.d.ts +3 -0
  249. package/dist/v1/schema/compatibility/meaning/index.js +16 -0
  250. package/dist/v1/schema/compatibility/model.d.ts +131 -0
  251. package/dist/v1/schema/compatibility/model.js +1 -0
  252. package/dist/v1/schema/compatibility/references.d.ts +38 -0
  253. package/dist/v1/schema/compatibility/references.js +149 -0
  254. package/dist/v1/schema/compatibility/report.d.ts +27 -0
  255. package/dist/v1/schema/compatibility/report.js +100 -0
  256. package/dist/v1/schema/compatibility/scope.d.ts +36 -0
  257. package/dist/v1/schema/compatibility/scope.js +110 -0
  258. package/dist/v1/schema/compatibility/structure/index.d.ts +3 -0
  259. package/dist/v1/schema/compatibility/structure/index.js +40 -0
  260. package/dist/v1/schema/compatibility/structure/inheritance.d.ts +7 -0
  261. package/dist/v1/schema/compatibility/structure/inheritance.js +68 -0
  262. package/dist/v1/schema/compatibility/structure/requirements.d.ts +7 -0
  263. package/dist/v1/schema/compatibility/structure/requirements.js +97 -0
  264. package/dist/v1/schema/compatibility/subjects.d.ts +39 -0
  265. package/dist/v1/schema/compatibility/subjects.js +143 -0
  266. package/dist/v1/schema/compatibility/versioning/index.d.ts +8 -0
  267. package/dist/v1/schema/compatibility/versioning/index.js +50 -0
  268. package/dist/v1/schema/compatibility/versioning/members.d.ts +12 -0
  269. package/dist/v1/schema/compatibility/versioning/members.js +47 -0
  270. package/dist/v1/schema/compatibility/versioning/surface.d.ts +11 -0
  271. package/dist/v1/schema/compatibility/versioning/surface.js +61 -0
  272. package/dist/v1/schema/diagnostic.d.ts +1 -1
  273. package/dist/v1/schema/fingerprint.d.ts +2 -0
  274. package/dist/v1/schema/fingerprint.js +1 -0
  275. package/dist/v1/schema/index.d.ts +4 -3
  276. package/dist/v1/schema/index.js +2 -1
  277. package/dist/v1/schema/model/schema.d.ts +8 -11
  278. package/dist/v1/schema/normalization/domain.js +57 -13
  279. package/dist/v1/schema/resolution/definition.index.d.ts +1 -2
  280. package/dist/v1/schema/resolution/definition.index.js +0 -3
  281. package/dist/v1/schema/resolution/domain.d.ts +4 -1
  282. package/dist/v1/schema/resolution/domain.js +26 -18
  283. package/dist/v1/schema/resolution/origins.d.ts +28 -5
  284. package/dist/v1/schema/resolution/origins.js +68 -31
  285. package/dist/v1/schema/validation/callable.d.ts +4 -0
  286. package/dist/v1/schema/validation/callable.js +39 -0
  287. package/dist/v1/schema/validation/class.d.ts +10 -0
  288. package/dist/v1/schema/validation/class.js +79 -60
  289. package/dist/v1/schema/validation/core.js +83 -55
  290. package/dist/v1/schema/validation/domain.d.ts +2 -1
  291. package/dist/v1/schema/validation/domain.js +2 -0
  292. package/dist/v1/schema/validation/domain.structure.d.ts +0 -2
  293. package/dist/v1/schema/validation/domain.structure.js +214 -171
  294. package/dist/v1/schema/validation/policy/budgets.js +36 -6
  295. package/dist/v1/schema/validation/policy/context.js +5 -16
  296. package/dist/v1/schema/validation/policy/objects.d.ts +4 -0
  297. package/dist/v1/schema/validation/policy/objects.js +71 -0
  298. package/dist/v1/schema/validation/policy/references.js +16 -4
  299. package/dist/v1/schema/validation/policy/typing.d.ts +2 -0
  300. package/dist/v1/schema/validation/policy/typing.js +55 -7
  301. package/dist/v1/schema/validation/policy/uses.js +73 -99
  302. package/dist/v1/schema/validation/value-api.d.ts +2 -0
  303. package/dist/v1/schema/validation/value-api.js +1 -0
  304. package/dist/v1/schema/validation/value.js +7 -1
  305. package/dist/v1/schema/validation/view.js +14 -9
  306. package/dist/value/accept.d.ts +9 -0
  307. package/dist/value/accept.js +106 -7
  308. package/dist/value/canonical.d.ts +3 -0
  309. package/dist/value/canonical.js +22 -6
  310. package/dist/value/immutable.optimization.d.ts +15 -0
  311. package/dist/value/immutable.optimization.js +34 -0
  312. package/dist/value/index.d.ts +1 -1
  313. package/dist/value/index.js +1 -1
  314. package/dist/value/json.d.ts +1 -1
  315. package/dist/value/json.js +1 -1
  316. package/dist/value/limits.d.ts +1 -1
  317. package/dist/value/unicode.d.ts +4 -1
  318. package/dist/value/unicode.js +28 -0
  319. package/package.json +20 -5
  320. package/dist/v1/schema/compatibility/meaning.d.ts +0 -29
  321. package/dist/v1/schema/compatibility/meaning.js +0 -605
@@ -1,4 +1,6 @@
1
1
  import { compareDefinitionRefs, definitionRefIndex } from '../../addressing/ordering.js';
2
+ import { isBinaryInput } from '../../language/callable/model/callable.js';
3
+ import { isClassRuleChecks, policyVariableClass } from '../../language/policy/model/policy.js';
2
4
  import { isValueObject as isJsonObject } from '../../language/value/model/object.js';
3
5
  import { walkSchema } from '../../language/value/syntax/walk.js';
4
6
  /** Collect only semantic refs, never strings or objects embedded as JSON data. */
@@ -11,7 +13,8 @@ export function collectUsedForeignOrigins(schema) {
11
13
  export function collectDomainDefinitionRefs(schema) {
12
14
  const result = new Map();
13
15
  const add = (ref) => {
14
- result.set(definitionRefIndex(ref), ref);
16
+ const definition = ref.kind === 'method' ? ref.owner : ref;
17
+ result.set(definitionRefIndex(definition), definition);
15
18
  };
16
19
  for (const declaration of Object.values(schema.classes)) {
17
20
  collectClassRefs(declaration, add);
@@ -22,51 +25,66 @@ export function collectDomainDefinitionRefs(schema) {
22
25
  for (const declaration of Object.values(schema.policies)) {
23
26
  collectPolicyDefinitionRefs(declaration, add);
24
27
  }
25
- for (const declaration of Object.values(schema.views)) {
26
- if (declaration.target.kind === 'definition')
27
- declaration.target.definitions.forEach(add);
28
- }
28
+ collectCoreRefs(schema, add);
29
+ return Object.freeze([...result.values()].sort(compareDefinitionRefs));
30
+ }
31
+ export function collectCoreRefs(schema, add) {
29
32
  for (const node of Object.values(schema.core.nodes))
30
- add(node.class);
33
+ add(node.class, 'core');
31
34
  for (const edge of schema.core.edges) {
32
- add(edge.class);
33
- if (edge.source.kind !== 'domain')
34
- add(edge.source);
35
- if (edge.target.kind !== 'domain')
36
- add(edge.target);
35
+ add(edge.class, 'core');
36
+ for (const endpoint of [edge.source, edge.target]) {
37
+ const ref = coreEndpointDefinitionRef(endpoint);
38
+ // An endpoint names the Definition without instantiating it, exactly like an accepts contract.
39
+ if (ref !== undefined)
40
+ add(ref, 'endpoint');
41
+ }
37
42
  }
38
- return Object.freeze([...result.values()].sort(compareDefinitionRefs));
43
+ }
44
+ /** The owning Domain addresses no Definition, and a Method is addressed through its owner Class. */
45
+ export function coreEndpointDefinitionRef(endpoint) {
46
+ if (endpoint.kind === 'domain')
47
+ return undefined;
48
+ return endpoint.kind === 'method' ? endpoint.owner : endpoint;
39
49
  }
40
50
  export function collectClassRefs(declaration, add) {
41
- declaration.extends.forEach(add);
51
+ declaration.extends.forEach((ref) => add(ref, 'extends'));
42
52
  Object.values(declaration.properties).forEach((property) => collectValueDefinitionRefs(property.schema, add));
53
+ collectClassPolicyRefs(declaration, add);
43
54
  if (declaration.kind === 'edge') {
44
55
  collectEndpointRefs(declaration, add);
45
- if (declaration.policies.traverse !== undefined)
46
- add(declaration.policies.traverse);
47
56
  return;
48
57
  }
49
58
  Object.values(declaration.methods).forEach((method) => collectCallableRefs(method, add));
50
- if (declaration.policies.read !== undefined)
51
- add(declaration.policies.read);
52
- if (declaration.policies.traverse !== undefined)
53
- add(declaration.policies.traverse);
54
59
  }
55
- function collectEndpointRefs(declaration, add) {
60
+ export function collectClassPolicyRefs(declaration, add) {
61
+ for (const policy of [declaration.policies.read, declaration.policies.traverse]) {
62
+ if (isClassRuleChecks(policy))
63
+ collectPolicyCheckRefs(policy, add);
64
+ else if (typeof policy === 'object')
65
+ add(policy, 'policy');
66
+ }
67
+ }
68
+ export function collectEndpointRefs(declaration, add) {
56
69
  const endpoints = declaration.orientation === 'directed'
57
70
  ? [declaration.endpoints.source, declaration.endpoints.target]
58
71
  : declaration.endpoints;
59
- endpoints[0].accepts.forEach(add);
60
- endpoints[1].accepts.forEach(add);
72
+ endpoints[0].accepts.forEach((ref) => add(ref, 'endpoint'));
73
+ endpoints[1].accepts.forEach((ref) => add(ref, 'endpoint'));
61
74
  }
62
75
  export function collectCallableRefs(declaration, add) {
63
- collectValueDefinitionRefs(declaration.input, add);
76
+ collectCallableContractRefs(declaration, add);
77
+ if (typeof declaration.policy === 'object') {
78
+ collectPolicyCheckRefs(declaration.policy, add);
79
+ }
80
+ }
81
+ /** References inside the contract a caller compiles against: the input and output value schemas. */
82
+ export function collectCallableContractRefs(declaration, add) {
83
+ collectValueDefinitionRefs(isBinaryInput(declaration.input) ? declaration.input.metadata : declaration.input, add);
64
84
  if (declaration.output.mode === 'value')
65
85
  collectValueDefinitionRefs(declaration.output.schema, add);
66
86
  if (declaration.output.mode === 'stream')
67
87
  collectValueDefinitionRefs(declaration.output.item, add);
68
- if (declaration.policy !== undefined)
69
- collectPolicyCheckRefs(declaration.policy, add);
70
88
  }
71
89
  export function collectPolicyDefinitionRefs(declaration, add) {
72
90
  collectPolicyExpressionRefs(declaration.expression, add);
@@ -77,15 +95,28 @@ function collectPolicyExpressionRefs(expression, add) {
77
95
  return;
78
96
  }
79
97
  const refs = 'allOf' in expression ? expression.allOf : expression.anyOf;
80
- refs.forEach(add);
98
+ refs.forEach((ref) => add(ref, 'policy'));
81
99
  }
82
100
  function collectPolicyPatternRefs(expression, add) {
101
+ if ('sameNode' in expression) {
102
+ for (const term of [expression.sameNode.left, expression.sameNode.right])
103
+ if (term.kind === 'ref')
104
+ add(term.ref, 'policy');
105
+ return;
106
+ }
83
107
  if ('source' in expression) {
84
- add(expression.class);
108
+ for (const term of [expression.source, expression.target])
109
+ if (term.kind === 'ref')
110
+ add(term.ref, 'policy');
111
+ add(expression.class, 'pattern');
85
112
  return;
86
113
  }
87
114
  if ('exists' in expression) {
88
- expression.exists.nodes.forEach((node) => add(node.class));
115
+ expression.exists.nodes.forEach((node) => {
116
+ const ref = policyVariableClass(node);
117
+ if (ref !== undefined)
118
+ add(ref, 'policy');
119
+ });
89
120
  collectPolicyPatternRefs(expression.exists.where, add);
90
121
  return;
91
122
  }
@@ -93,10 +124,16 @@ function collectPolicyPatternRefs(expression, add) {
93
124
  children.forEach((child) => collectPolicyPatternRefs(child, add));
94
125
  }
95
126
  function collectPolicyCheckRefs(expression, add) {
127
+ if ('sameNode' in expression) {
128
+ for (const term of [expression.sameNode.left, expression.sameNode.right])
129
+ if (term.kind === 'ref')
130
+ add(term.ref, 'policy');
131
+ return;
132
+ }
96
133
  if ('check' in expression) {
97
- add(expression.check);
134
+ add(expression.check, 'policy');
98
135
  if (expression.object.kind === 'ref')
99
- add(expression.object.ref);
136
+ add(expression.object.ref, 'policy');
100
137
  return;
101
138
  }
102
139
  const children = 'allOf' in expression ? expression.allOf : expression.anyOf;
@@ -114,7 +151,7 @@ export function collectValueDefinitionRefs(schema, add) {
114
151
  typeof candidate.origin === 'string' &&
115
152
  typeof candidate.kind === 'string' &&
116
153
  typeof candidate.name === 'string') {
117
- add(candidate);
154
+ add(candidate, 'value');
118
155
  }
119
156
  }
120
157
  });
@@ -0,0 +1,4 @@
1
+ import type { SchemaDiagnostic } from '../diagnostic.js';
2
+ import type { DomainSchemaIR } from '../model/schema.js';
3
+ /** Validate the execution modifier of every local Function and Node Method. */
4
+ export declare function validateCallables(schema: DomainSchemaIR): readonly SchemaDiagnostic[];
@@ -0,0 +1,39 @@
1
+ import { isBinaryInput } from '../../language/callable/model/callable.js';
2
+ import { diagnostic } from '../diagnostic.js';
3
+ /** Validate the execution modifier of every local Function and Node Method. */
4
+ export function validateCallables(schema) {
5
+ const diagnostics = [];
6
+ for (const [name, declaration] of Object.entries(schema.functions)) {
7
+ validateExecution(declaration, `/functions/${escapePointer(name)}`, diagnostics);
8
+ }
9
+ for (const [name, declaration] of Object.entries(schema.classes)) {
10
+ if (declaration.kind !== 'node')
11
+ continue;
12
+ for (const [method, value] of Object.entries(declaration.methods)) {
13
+ const pointer = `/classes/${escapePointer(name)}/methods/${escapePointer(method)}`;
14
+ validateExecution(value, pointer, diagnostics);
15
+ }
16
+ }
17
+ return Object.freeze(diagnostics);
18
+ }
19
+ /**
20
+ * An Execution records its initiating caller and its admitted input, from which the run is
21
+ * resubmitted, and retains one portable outcome. A durable callable therefore needs a known caller,
22
+ * a value input and a replayable value output.
23
+ */
24
+ function validateExecution(declaration, pointer, diagnostics) {
25
+ if (declaration.execution?.durable !== true)
26
+ return;
27
+ if (declaration.auth === 'anonymous') {
28
+ diagnostics.push(diagnostic('DV_CALLABLE_AUTH', `${pointer}/auth`, 'A durable callable requires authenticated or authorized auth.'));
29
+ }
30
+ if (isBinaryInput(declaration.input)) {
31
+ diagnostics.push(diagnostic('DV_CALLABLE_IO', `${pointer}/input/mode`, 'A durable callable requires a value input.'));
32
+ }
33
+ if (declaration.output.mode !== 'value') {
34
+ diagnostics.push(diagnostic('DV_CALLABLE_IO', `${pointer}/output/mode`, 'A durable callable requires a value output.'));
35
+ }
36
+ }
37
+ function escapePointer(value) {
38
+ return value.replaceAll('~', '~0').replaceAll('/', '~1');
39
+ }
@@ -1,5 +1,15 @@
1
+ import type { ClassRef } from '../../addressing/index.js';
2
+ import type { ClassDefinition } from '../../language/class/model/class.js';
1
3
  import type { DefinitionAnalysisResult } from '../analysis/class.js';
2
4
  import type { SchemaDiagnostic } from '../diagnostic.js';
3
5
  import type { DomainResolutionContext } from '../resolution/context.js';
4
6
  /** Validate the semantic contracts owned by Class declarations. */
5
7
  export declare function validateDefinitions(environment: DomainResolutionContext, analysis: DefinitionAnalysisResult): readonly SchemaDiagnostic[];
8
+ /** Whether `child` safely refines its parent Edge contract `parent`. */
9
+ export declare function edgeContractRefines(environment: DomainResolutionContext, child: Extract<ClassDefinition, {
10
+ readonly kind: 'edge';
11
+ }>, parent: Extract<ClassDefinition, {
12
+ readonly kind: 'edge';
13
+ }>): boolean;
14
+ /** Whether `candidate` is, or is a Node Class extending, one of `accepts`. */
15
+ export declare function classSatisfies(environment: DomainResolutionContext, candidate: ClassRef, accepts: readonly ClassRef[]): boolean;
@@ -1,5 +1,9 @@
1
1
  import { Key } from '../../addressing/key.js';
2
2
  import { definitionRefIndex } from '../../addressing/ordering.js';
3
+ import { isMethodExecutable } from '../../language/callable/executable.js';
4
+ import { classSatisfies as satisfiesClass, isGraphRoot } from '../../language/class/inheritance.js';
5
+ import { admitStateTopology } from '../../language/state/topology.js';
6
+ import { isBlobValueSchema } from '../../language/value/model/blob.js';
3
7
  import { classifyOrdering } from '../../language/value/ordering.js';
4
8
  import { diagnostic } from '../diagnostic.js';
5
9
  import { createValueSchemaRegistry } from '../resolution/value.registry.js';
@@ -14,6 +18,10 @@ export function validateDefinitions(environment, analysis) {
14
18
  if (!sameRef(declaration.ref, ref)) {
15
19
  diagnostics.push(diagnostic('DV_REF_RESOLVES', `${pointer}/ref`, `Class ref must be exactly ${formatDefinitionRef(ref)}.`, formatDefinitionRef(declaration.ref)));
16
20
  }
21
+ if (declaration.abstract &&
22
+ (declaration.policies.read !== undefined || declaration.policies.traverse !== undefined)) {
23
+ diagnostics.push(diagnostic('DV_CLASS_ABSTRACT', `${pointer}/policies`, 'Abstract Classes cannot declare observation Policies.'));
24
+ }
17
25
  validateFacet(environment, declaration, pointer, diagnostics);
18
26
  validateParents(environment, ref, declaration.kind, declaration.extends, diagnostics);
19
27
  if (declaration.kind === 'edge') {
@@ -26,22 +34,60 @@ export function validateDefinitions(environment, analysis) {
26
34
  function validateFacet(environment, declaration, pointer, diagnostics) {
27
35
  const valueRegistry = createValueSchemaRegistry(environment);
28
36
  for (const [name, property] of Object.entries(declaration.properties)) {
37
+ const propertyPointer = `${pointer}/properties/${escapePointer(name)}`;
38
+ if (isBlobValueSchema(property.schema) &&
39
+ (declaration.kind !== 'node' || property.auto !== undefined || property.state !== undefined)) {
40
+ diagnostics.push(diagnostic('DV_VALUE_SCHEMA', `${propertyPointer}/schema/x-astrale-value-kind`, 'Blob values are allowed only on non-automatic, non-state Node properties.'));
41
+ }
42
+ if (property.state !== undefined) {
43
+ if (declaration.kind !== 'node') {
44
+ diagnostics.push(diagnostic('DV_PROPERTY_STATE', `${propertyPointer}/state`, 'A State Property may be declared only on a Node Class.'));
45
+ }
46
+ try {
47
+ const topology = admitStateTopology(property.state);
48
+ const expected = Object.keys(topology.transitions).sort();
49
+ const schema = property.schema;
50
+ const schemaMatches = schema !== null &&
51
+ typeof schema === 'object' &&
52
+ !Array.isArray(schema) &&
53
+ Object.keys(schema).length === 2 &&
54
+ schema.type === 'string' &&
55
+ Array.isArray(schema.enum) &&
56
+ schema.enum.length === expected.length &&
57
+ [...schema.enum].sort().every((state, index) => state === expected[index]);
58
+ if (!property.required || property.auto !== undefined || !schemaMatches) {
59
+ diagnostics.push(diagnostic('DV_PROPERTY_STATE', `${propertyPointer}/state`, 'A State Property is required, non-automatic, and has exactly its declared states.'));
60
+ }
61
+ }
62
+ catch (error) {
63
+ diagnostics.push(diagnostic('DV_PROPERTY_STATE', `${propertyPointer}/state`, error instanceof Error ? error.message : 'Invalid State topology.'));
64
+ }
65
+ }
66
+ if (property.immutable !== undefined) {
67
+ const immutablePointer = `${propertyPointer}/immutable`;
68
+ if (property.auto !== undefined || property.state !== undefined) {
69
+ diagnostics.push(diagnostic('DV_PROPERTY_IMMUTABLE', immutablePointer, 'An immutable Property is neither automatic nor a State Property.'));
70
+ }
71
+ if (property.immutable === 'once' && property.required) {
72
+ diagnostics.push(diagnostic('DV_PROPERTY_IMMUTABLE', immutablePointer, 'A required immutable Property is written at creation: declare it create, not once.'));
73
+ }
74
+ }
29
75
  if (property.auto === undefined)
30
76
  continue;
31
- const propertyPointer = `${pointer}/properties/${escapePointer(name)}/auto`;
77
+ const autoPointer = `${propertyPointer}/auto`;
32
78
  if (property.required && !property.auto.on.includes('create')) {
33
- diagnostics.push(diagnostic('DV_PROPERTY_AUTO', `${propertyPointer}/on`, 'A required auto Property must run on create.'));
79
+ diagnostics.push(diagnostic('DV_PROPERTY_AUTO', `${autoPointer}/on`, 'A required auto Property must run on create.'));
34
80
  }
35
81
  if (property.auto.set === 'instant' &&
36
82
  classifyOrdering(property.schema, valueRegistry) !== 'instant') {
37
- diagnostics.push(diagnostic('DV_PROPERTY_AUTO', `${propertyPointer}/set`, 'The instant setter requires an Instant value schema.'));
83
+ diagnostics.push(diagnostic('DV_PROPERTY_AUTO', `${autoPointer}/set`, 'The instant setter requires an Instant value schema.'));
38
84
  }
39
85
  }
40
86
  if (declaration.kind !== 'node')
41
87
  return;
42
88
  for (const [name, method] of Object.entries(declaration.methods)) {
43
89
  const methodPointer = `${pointer}/methods/${escapePointer(name)}`;
44
- if (method.inheritance === 'abstract' && method.policy !== undefined) {
90
+ if (!isMethodExecutable(declaration, method) && method.policy !== undefined) {
45
91
  diagnostics.push(diagnostic('DV_METHOD_ABSTRACT', `${methodPointer}/policy`, 'Abstract Methods cannot have a Policy.'));
46
92
  }
47
93
  }
@@ -66,19 +112,24 @@ function validateEdgeContract(environment, owner, declaration, diagnostics) {
66
112
  if (endpoints[0].role === endpoints[1].role) {
67
113
  diagnostics.push(diagnostic('DV_EDGE_ROLE', '', `${formatDefinitionRef(owner)} has equal endpoint roles.`));
68
114
  }
69
- validateEndpoint(environment, owner, endpoints[0], declaration.orientation === 'directed' ? 'source' : 'first endpoint', diagnostics);
70
- validateEndpoint(environment, owner, endpoints[1], declaration.orientation === 'directed' ? 'target' : 'second endpoint', diagnostics);
115
+ const counts = declaration.orientation === 'directed'
116
+ ? [declaration.endpoints.source.outgoing, declaration.endpoints.target.incoming]
117
+ : [declaration.endpoints[0].incident, declaration.endpoints[1].incident];
118
+ validateEndpoint(environment, owner, endpoints[0], counts[0], declaration.orientation === 'directed' ? 'source' : 'first endpoint', diagnostics);
119
+ validateEndpoint(environment, owner, endpoints[1], counts[1], declaration.orientation === 'directed' ? 'target' : 'second endpoint', diagnostics);
71
120
  if (declaration.orientation === 'undirected') {
72
- if (!sameIncidentEndpointContract(declaration.endpoints[0], declaration.endpoints[1]) &&
73
- undirectedEndpointsOverlap(environment, declaration.endpoints)) {
74
- diagnostics.push(diagnostic('DV_EDGE_UNDIRECTED', '', `${formatDefinitionRef(owner)} has unequal undirected endpoint contracts whose accepted Node families overlap.`));
75
- }
76
121
  if (declaration.constraints.acyclic === true) {
77
122
  diagnostics.push(diagnostic('DV_EDGE_CONSTRAINT', '', 'acyclic is valid only for directed Edge contracts.'));
78
123
  }
79
124
  }
80
125
  }
81
- function validateEndpoint(environment, owner, endpoint, side, diagnostics) {
126
+ function validateEndpoint(environment, owner, endpoint, count, side, diagnostics) {
127
+ // An Edge Class binds only the Nodes of its Domain and its dependents: it cannot oblige the
128
+ // Nodes of a Class another Domain owns to carry its Edges.
129
+ const foreign = endpoint.accepts.find((ref) => ref.origin !== owner.origin);
130
+ if (foreign !== undefined && (count === '1' || count === '1..*')) {
131
+ diagnostics.push(diagnostic('DV_EDGE_FOREIGN_MINIMUM', '', `${formatDefinitionRef(owner)} ${side} accepts ${formatDefinitionRef(foreign)} of another Domain and cannot require ${count} Edges.`));
132
+ }
82
133
  const seen = new Set();
83
134
  for (const ref of endpoint.accepts) {
84
135
  const key = definitionRefIndex(ref);
@@ -113,7 +164,10 @@ function validateEdgeClassComposition(environment, diagnostics) {
113
164
  }
114
165
  }
115
166
  }
116
- function edgeContractRefines(environment, child, parent) {
167
+ /** Whether `child` safely refines its parent Edge contract `parent`. */
168
+ export function edgeContractRefines(environment, child, parent) {
169
+ if (isGraphRoot(parent))
170
+ return true;
117
171
  if (child.orientation !== parent.orientation)
118
172
  return false;
119
173
  if (parent.constraints.noSelf === true && child.constraints.noSelf !== true)
@@ -130,7 +184,10 @@ function edgeContractRefines(environment, child, parent) {
130
184
  return false;
131
185
  const refines = (childIndex, parentIndex) => endpointRefines(environment, child.endpoints[childIndex], parent.endpoints[parentIndex]) &&
132
186
  countRefines(child.endpoints[childIndex].incident, parent.endpoints[parentIndex].incident);
133
- return (refines(0, 0) && refines(1, 1)) || (refines(0, 1) && refines(1, 0));
187
+ const direct = refines(0, 0) && refines(1, 1);
188
+ if (direct)
189
+ return true;
190
+ return refines(0, 1) && refines(1, 0);
134
191
  }
135
192
  function endpointRefines(environment, child, parent) {
136
193
  return child.accepts.every((accepted) => classSatisfies(environment, accepted, parent.accepts));
@@ -146,56 +203,18 @@ function countRefines(child, parent) {
146
203
  const [parentMinimum, parentMaximum] = bounds[parent];
147
204
  return childMinimum >= parentMinimum && childMaximum <= parentMaximum;
148
205
  }
149
- function sameIncidentEndpointContract(left, right) {
150
- if (left.incident !== right.incident)
151
- return false;
152
- const a = [...left.accepts].map(definitionRefIndex).sort();
153
- const b = [...right.accepts].map(definitionRefIndex).sort();
154
- return a.length === b.length && a.every((value, index) => value === b[index]);
155
- }
156
- function undirectedEndpointsOverlap(environment, endpoints) {
157
- for (const resolved of environment.definitions.values()) {
158
- if (resolved.ref.kind !== 'class' ||
159
- resolved.declaration.kind !== 'node' ||
160
- resolved.declaration.abstract) {
161
- continue;
162
- }
163
- const candidate = resolved.ref;
164
- if (classSatisfies(environment, candidate, endpoints[0].accepts) &&
165
- classSatisfies(environment, candidate, endpoints[1].accepts)) {
166
- return true;
167
- }
168
- }
169
- return false;
170
- }
171
- function classSatisfies(environment, candidate, accepts) {
206
+ /** Whether `candidate` is, or is a Node Class extending, one of `accepts`. */
207
+ export function classSatisfies(environment, candidate, accepts) {
172
208
  if (accepts.some((ref) => definitionRefIndex(ref) === definitionRefIndex(candidate)))
173
209
  return true;
174
- const resolved = environment.resolveAny(candidate);
175
- if (resolved === undefined ||
176
- resolved.ref.kind !== 'class' ||
177
- resolved.declaration.kind !== 'node') {
210
+ const resolve = (ref) => environment.resolveAny(ref)?.declaration;
211
+ const actual = resolve(candidate);
212
+ if (actual?.kind !== 'node')
178
213
  return false;
179
- }
180
- return extendsAny(environment, resolved.declaration.extends, accepts, new Set());
181
- }
182
- function extendsAny(environment, parents, accepts, visited) {
183
- const accepted = new Set(accepts.map(definitionRefIndex));
184
- for (const parent of parents) {
185
- const key = definitionRefIndex(parent);
186
- if (accepted.has(key))
187
- return true;
188
- if (visited.has(key))
189
- continue;
190
- visited.add(key);
191
- const resolved = environment.resolveAny(parent);
192
- if (resolved !== undefined &&
193
- resolved.ref.kind === 'class' &&
194
- extendsAny(environment, resolved.declaration.extends, accepts, visited)) {
195
- return true;
196
- }
197
- }
198
- return false;
214
+ return accepts.some((ref) => {
215
+ const required = resolve(ref);
216
+ return required !== undefined && satisfiesClass(actual, required, resolve);
217
+ });
199
218
  }
200
219
  function localRef(origin, name) {
201
220
  return { origin, kind: 'class', name };
@@ -1,7 +1,10 @@
1
1
  import { Key } from '../../addressing/key.js';
2
2
  import { compareUnicode, definitionRefIndex } from '../../addressing/ordering.js';
3
+ import { isMethodExecutable } from '../../language/callable/executable.js';
4
+ import { policyObjectKey, policyObjectOrigin, projectedMemberClass, } from '../../language/policy/model/policy.js';
3
5
  import { validateJsonInstance } from '../../language/value/evaluate/validate.js';
4
6
  import { diagnostic } from '../diagnostic.js';
7
+ import { classSatisfies } from './class.js';
5
8
  const formatDefinitionRef = Key.of;
6
9
  export function validateCore(environment, analysis, registry) {
7
10
  const diagnostics = [];
@@ -42,8 +45,8 @@ function resolveCoreEdges(environment, analysis, registry, nodesByRef, diagnosti
42
45
  const edges = [];
43
46
  for (const [index, edge] of environment.candidate.core.edges.entries()) {
44
47
  const pointer = `/core/edges/${index}`;
45
- const source = resolveCoreEndpoint(edge.source, `${pointer}/source`, nodesByRef, diagnostics);
46
- const target = resolveCoreEndpoint(edge.target, `${pointer}/target`, nodesByRef, diagnostics);
48
+ const source = resolveCoreEndpoint(environment, edge.source, `${pointer}/source`, nodesByRef, diagnostics);
49
+ const target = resolveCoreEndpoint(environment, edge.target, `${pointer}/target`, nodesByRef, diagnostics);
47
50
  const resolved = environment.resolve(edge.class);
48
51
  if (edge.class.origin !== environment.candidate.origin ||
49
52
  resolved === undefined ||
@@ -75,14 +78,37 @@ function resolveCoreEdges(environment, analysis, registry, nodesByRef, diagnosti
75
78
  }
76
79
  return edges;
77
80
  }
78
- function resolveCoreEndpoint(ref, pointer, nodesByRef, diagnostics) {
81
+ function resolveCoreEndpoint(environment, ref, pointer, nodesByRef, diagnostics) {
79
82
  if (ref.kind === 'domain')
80
83
  return { kind: 'domain', ref, key: 'domain' };
81
- const node = nodesByRef.get(definitionRefIndex(ref));
82
- if (node === undefined) {
83
- diagnostics.push(diagnostic('DV_CORE_REF', pointer, `Core endpoint ${formatDefinitionRef(ref)} does not name a declared local Core Node.`, formatDefinitionRef(ref)));
84
+ const undeclared = () => {
85
+ const key = policyObjectKey(ref);
86
+ diagnostics.push(diagnostic('DV_CORE_REF', pointer, `Core endpoint ${key} does not name a declared local Definition.`, key));
87
+ return undefined;
88
+ };
89
+ if (policyObjectOrigin(ref) !== environment.candidate.origin)
90
+ return undeclared();
91
+ if (ref.kind === 'core')
92
+ return nodesByRef.get(definitionRefIndex(ref)) ?? undeclared();
93
+ if (!declaresProjectedMember(environment, ref))
94
+ return undeclared();
95
+ return { kind: 'member', key: policyObjectKey(ref), classRef: projectedMemberClass(ref) };
96
+ }
97
+ /** Only a projected declaration can carry a Core fact; an abstract Method is never projected. */
98
+ function declaresProjectedMember(environment, ref) {
99
+ const candidate = environment.candidate;
100
+ if (ref.kind === 'method') {
101
+ const owner = candidate.classes[ref.owner.name];
102
+ const method = owner?.kind === 'node' ? owner.methods[ref.name] : undefined;
103
+ return method !== undefined && isMethodExecutable(owner, method);
84
104
  }
85
- return node;
105
+ if (ref.kind === 'class')
106
+ return Object.hasOwn(candidate.classes, ref.name);
107
+ if (ref.kind === 'function')
108
+ return Object.hasOwn(candidate.functions, ref.name);
109
+ if (ref.kind === 'policy')
110
+ return Object.hasOwn(candidate.policies, ref.name);
111
+ return Object.hasOwn(candidate.views, ref.name);
86
112
  }
87
113
  function endpointSatisfies(environment, endpoint, accepts) {
88
114
  // The owning Domain is a graph-projection identity, not a Definition declared by this DSL.
@@ -92,9 +118,11 @@ function endpointSatisfies(environment, endpoint, accepts) {
92
118
  function validateCreationProperties(definition, properties, registry, code, pointer, diagnostics) {
93
119
  const schema = {
94
120
  type: 'object',
95
- properties: Object.fromEntries([...definition.properties].map(([name, field]) => [name, field.schema])),
121
+ properties: Object.fromEntries([...definition.properties]
122
+ .filter(([, field]) => field.auto === undefined)
123
+ .map(([name, field]) => [name, field.schema])),
96
124
  required: [...definition.properties]
97
- .filter(([, field]) => field.required)
125
+ .filter(([, field]) => field.required && field.auto === undefined)
98
126
  .map(([name]) => name)
99
127
  .sort(compareUnicode),
100
128
  additionalProperties: false,
@@ -155,41 +183,68 @@ function validateCoreEdgeSet(environment, edges, nodesByRef, diagnostics) {
155
183
  }
156
184
  }
157
185
  function validateCardinality(environment, declaration, edges, nodesByRef, diagnostics) {
186
+ const subjects = cardinalitySubjects(edges, nodesByRef);
158
187
  if (declaration.orientation === 'undirected') {
159
188
  const [first, second] = declaration.endpoints;
160
- for (const node of nodesByRef.values()) {
161
- const matchesFirst = classSatisfies(environment, node.classRef, first.accepts);
162
- const matchesSecond = classSatisfies(environment, node.classRef, second.accepts);
189
+ for (const subject of subjects) {
190
+ const matchesFirst = classSatisfies(environment, subject.classRef, first.accepts);
191
+ const matchesSecond = classSatisfies(environment, subject.classRef, second.accepts);
163
192
  if (!matchesFirst && !matchesSecond)
164
193
  continue;
165
- const degree = edges.filter((edge) => edge.source.key === node.key || edge.target.key === node.key).length;
194
+ const degree = edges.filter((edge) => edge.source.key === subject.key || edge.target.key === subject.key).length;
166
195
  if (matchesFirst)
167
- checkIncidentBound(first, degree, node, diagnostics);
196
+ checkBound(first, first.incident, degree, subject, diagnostics);
168
197
  if (matchesSecond && !sameIncidentEndpointContract(first, second)) {
169
- checkIncidentBound(second, degree, node, diagnostics);
198
+ checkBound(second, second.incident, degree, subject, diagnostics);
170
199
  }
171
200
  }
172
201
  return;
173
202
  }
174
- for (const node of nodesByRef.values()) {
175
- if (classSatisfies(environment, node.classRef, declaration.endpoints.source.accepts)) {
176
- const degree = edges.filter((edge) => edge.source.key === node.key).length;
177
- checkBound(declaration.endpoints.source, declaration.endpoints.source.outgoing, degree, node, diagnostics);
203
+ for (const subject of subjects) {
204
+ if (classSatisfies(environment, subject.classRef, declaration.endpoints.source.accepts)) {
205
+ const degree = edges.filter((edge) => edge.source.key === subject.key).length;
206
+ checkBound(declaration.endpoints.source, declaration.endpoints.source.outgoing, degree, subject, diagnostics);
178
207
  }
179
- if (classSatisfies(environment, node.classRef, declaration.endpoints.target.accepts)) {
180
- const degree = edges.filter((edge) => edge.target.key === node.key).length;
181
- checkBound(declaration.endpoints.target, declaration.endpoints.target.incoming, degree, node, diagnostics);
208
+ if (classSatisfies(environment, subject.classRef, declaration.endpoints.target.accepts)) {
209
+ const degree = edges.filter((edge) => edge.target.key === subject.key).length;
210
+ checkBound(declaration.endpoints.target, declaration.endpoints.target.incoming, degree, subject, diagnostics);
211
+ }
212
+ }
213
+ }
214
+ /**
215
+ * Every declared Core Node proves its own complete degree, so both bounds hold. A Definition
216
+ * endpoint is only named by the Edges that reach it: the Domain may also create ordinary Edges of
217
+ * the same Class against it, so a minimum is unprovable here and only the maximum is enforced.
218
+ */
219
+ function cardinalitySubjects(edges, nodesByRef) {
220
+ const subjects = new Map();
221
+ for (const node of nodesByRef.values()) {
222
+ subjects.set(node.key, {
223
+ key: node.key,
224
+ classRef: node.classRef,
225
+ pointer: `/core/nodes/${escapePointer(node.slug)}`,
226
+ minimum: true,
227
+ });
228
+ }
229
+ for (const edge of edges) {
230
+ for (const endpoint of [edge.source, edge.target]) {
231
+ if (endpoint.kind !== 'member' || subjects.has(endpoint.key))
232
+ continue;
233
+ subjects.set(endpoint.key, {
234
+ key: endpoint.key,
235
+ classRef: endpoint.classRef,
236
+ pointer: edge.pointer,
237
+ minimum: false,
238
+ });
182
239
  }
183
240
  }
241
+ return Object.freeze([...subjects.values()]);
184
242
  }
185
- function checkBound(endpoint, count, degree, node, diagnostics) {
243
+ function checkBound(endpoint, count, degree, subject, diagnostics) {
186
244
  const [minimum, maximum] = countBounds(count);
187
- if (degree >= minimum && degree <= maximum)
245
+ if (degree <= maximum && (degree >= minimum || !subject.minimum))
188
246
  return;
189
- diagnostics.push(diagnostic('DV_CORE_EDGE_CONSTRAINTS', `/core/nodes/${escapePointer(node.slug)}`, `Core degree ${degree} violates ${endpoint.role} Edge count ${count}.`));
190
- }
191
- function checkIncidentBound(endpoint, degree, node, diagnostics) {
192
- checkBound(endpoint, endpoint.incident, degree, node, diagnostics);
247
+ diagnostics.push(diagnostic('DV_CORE_EDGE_CONSTRAINTS', subject.pointer, `Core degree ${degree} violates ${endpoint.role} Edge count ${count}.`));
193
248
  }
194
249
  function sameIncidentEndpointContract(left, right) {
195
250
  return (left.incident === right.incident &&
@@ -232,33 +287,6 @@ function hasDirectedCycle(edges) {
232
287
  };
233
288
  return [...outgoing.keys()].some(visit);
234
289
  }
235
- function classSatisfies(environment, classRef, accepts) {
236
- if (accepts.some((ref) => definitionRefIndex(ref) === definitionRefIndex(classRef)))
237
- return true;
238
- const resolved = environment.resolveAny(classRef);
239
- if (resolved === undefined || resolved.ref.kind !== 'class' || resolved.kind !== 'node') {
240
- return false;
241
- }
242
- return classExtendsAny(environment, resolved.declaration.extends, accepts, new Set());
243
- }
244
- function classExtendsAny(environment, parents, accepts, visited) {
245
- const accepted = new Set(accepts.map(definitionRefIndex));
246
- for (const parent of parents) {
247
- const key = definitionRefIndex(parent);
248
- if (accepted.has(key))
249
- return true;
250
- if (visited.has(key))
251
- continue;
252
- visited.add(key);
253
- const resolved = environment.resolveAny(parent);
254
- if (resolved !== undefined &&
255
- resolved.ref.kind === 'class' &&
256
- classExtendsAny(environment, resolved.declaration.extends, accepts, visited)) {
257
- return true;
258
- }
259
- }
260
- return false;
261
- }
262
290
  function escapePointer(value) {
263
291
  return value.replaceAll('~', '~0').replaceAll('/', '~1');
264
292
  }
@@ -3,9 +3,10 @@ import type { DomainSchemaLookup } from '../dependency/lookup.js';
3
3
  import type { SchemaDiagnostic } from '../diagnostic.js';
4
4
  import type { DomainSchemaIR } from '../model/schema.js';
5
5
  import type { DomainResolutionContext } from '../resolution/context.js';
6
- export interface DomainSchemaValidation {
6
+ interface DomainSchemaValidation {
7
7
  readonly context: DomainResolutionContext;
8
8
  readonly analysis: DefinitionAnalysisResult;
9
9
  readonly diagnostics: readonly SchemaDiagnostic[];
10
10
  }
11
11
  export declare function validateDomainSchemaSemantics(schema: DomainSchemaIR, lookup: DomainSchemaLookup): DomainSchemaValidation;
12
+ export {};