@astrale-os/kernel-dsl 0.2.0-beta.9 → 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 +19 -3
  320. package/dist/v1/schema/compatibility/meaning.d.ts +0 -29
  321. package/dist/v1/schema/compatibility/meaning.js +0 -605
@@ -0,0 +1,28 @@
1
+ import type { PolicyCheckExpression } from '../model/policy.js';
2
+ export type PolicyCheckLeaf = Extract<PolicyCheckExpression, {
3
+ readonly check: unknown;
4
+ }>;
5
+ /** How one check leaf types against the Classes its object accepts. */
6
+ export interface CheckLeafClasses {
7
+ /** Every Class the leaf's object accepts. */
8
+ readonly accepted: readonly string[];
9
+ /** The accepted Classes at least one normalized branch of the leaf's Policy is typed for. */
10
+ readonly admitted: ReadonlySet<string>;
11
+ }
12
+ /**
13
+ * The Classes a leaf admits, from the typing of each normalized branch of its Policy for each
14
+ * accepted Class of its object. `undefined` when the Policy does not expand, or when one branch is
15
+ * typed for no accepted Class: that branch can never match this object, so it is refused rather
16
+ * than silently erased.
17
+ */
18
+ export declare function admittedCheckClasses(typing: ReadonlyMap<string, readonly boolean[] | undefined>): ReadonlySet<string> | undefined;
19
+ /**
20
+ * The accepted Classes of each object that the whole check tree can never admit.
21
+ *
22
+ * The tree is read in disjunctive normal form. A conjunction admits Class C of object O when every
23
+ * leaf over O in it admits C and every other object it checks keeps a Class that all of its leaves
24
+ * over that object admit; an object the conjunction does not check keeps every accepted Class.
25
+ * `sameNode` compares identities, not Classes, so it never removes a Class here. A tree over the
26
+ * check budget is already refused, so it is not expanded.
27
+ */
28
+ export declare function neverAdmittedClasses(expression: PolicyCheckExpression, leaves: ReadonlyMap<PolicyCheckLeaf, CheckLeafClasses>): readonly (readonly [object: string, className: string])[];
@@ -0,0 +1,80 @@
1
+ import { policyObjectKey } from '../model/policy.js';
2
+ import { MAX_BRANCHES, measureChecks } from './budgets.js';
3
+ /** Names a callable check object. Every leaf over one object sees the same Node at runtime. */
4
+ function checkObjectName(object) {
5
+ if (object.kind === 'self')
6
+ return 'self';
7
+ if (object.kind === 'input')
8
+ return `input.${object.field}`;
9
+ return policyObjectKey(object.ref);
10
+ }
11
+ /**
12
+ * The Classes a leaf admits, from the typing of each normalized branch of its Policy for each
13
+ * accepted Class of its object. `undefined` when the Policy does not expand, or when one branch is
14
+ * typed for no accepted Class: that branch can never match this object, so it is refused rather
15
+ * than silently erased.
16
+ */
17
+ export function admittedCheckClasses(typing) {
18
+ const rows = [...typing];
19
+ if (!rows.every((row) => row[1] !== undefined)) {
20
+ return undefined;
21
+ }
22
+ const branches = Math.max(0, ...rows.map(([, row]) => row.length));
23
+ for (let index = 0; index < branches; index++) {
24
+ if (!rows.some(([, row]) => row[index] === true))
25
+ return undefined;
26
+ }
27
+ return new Set(rows.filter(([, row]) => row.some(Boolean)).map(([name]) => name));
28
+ }
29
+ /**
30
+ * The accepted Classes of each object that the whole check tree can never admit.
31
+ *
32
+ * The tree is read in disjunctive normal form. A conjunction admits Class C of object O when every
33
+ * leaf over O in it admits C and every other object it checks keeps a Class that all of its leaves
34
+ * over that object admit; an object the conjunction does not check keeps every accepted Class.
35
+ * `sameNode` compares identities, not Classes, so it never removes a Class here. A tree over the
36
+ * check budget is already refused, so it is not expanded.
37
+ */
38
+ export function neverAdmittedClasses(expression, leaves) {
39
+ if (measureChecks(expression).branches > MAX_BRANCHES)
40
+ return [];
41
+ const accepted = new Map();
42
+ for (const [leaf, classes] of leaves)
43
+ accepted.set(checkObjectName(leaf.object), classes.accepted);
44
+ const admitted = new Map();
45
+ for (const conjunction of disjunctiveForm(expression)) {
46
+ const constrained = new Map();
47
+ for (const leaf of conjunction) {
48
+ if (!('check' in leaf))
49
+ continue;
50
+ const classes = leaves.get(leaf);
51
+ if (classes === undefined)
52
+ continue;
53
+ const object = checkObjectName(leaf.object);
54
+ const previous = constrained.get(object);
55
+ constrained.set(object, previous === undefined
56
+ ? classes.admitted
57
+ : new Set([...previous].filter((name) => classes.admitted.has(name))));
58
+ }
59
+ if ([...constrained.values()].some((classes) => classes.size === 0))
60
+ continue;
61
+ for (const [object, all] of accepted) {
62
+ const reached = admitted.get(object) ?? new Set();
63
+ for (const name of constrained.get(object) ?? all)
64
+ reached.add(name);
65
+ admitted.set(object, reached);
66
+ }
67
+ }
68
+ return [...accepted].flatMap(([object, all]) => all
69
+ .filter((name) => admitted.get(object)?.has(name) !== true)
70
+ .map((name) => [object, name]));
71
+ }
72
+ function disjunctiveForm(expression) {
73
+ if ('check' in expression || 'sameNode' in expression)
74
+ return [[expression]];
75
+ if ('anyOf' in expression)
76
+ return expression.anyOf.flatMap(disjunctiveForm);
77
+ return expression.allOf
78
+ .map(disjunctiveForm)
79
+ .reduce((left, right) => left.flatMap((prefix) => right.map((suffix) => [...prefix, ...suffix])), [[]]);
80
+ }
@@ -1,3 +1,4 @@
1
1
  export type * from './model/policy.js';
2
+ export { isClassRuleChecks, policyVariableClass, policyVariableSelector, policyObjectKey, policyObjectOrigin, projectedMemberClass, } from './model/policy.js';
2
3
  export type * from './resolved.js';
3
4
  export * from './normalization/normalize.js';
@@ -1 +1,2 @@
1
+ export { isClassRuleChecks, policyVariableClass, policyVariableSelector, policyObjectKey, policyObjectOrigin, projectedMemberClass, } from './model/policy.js';
1
2
  export * from './normalization/normalize.js';
@@ -1,4 +1,4 @@
1
- import type { CoreRef, ClassRef, FunctionRef, PolicyRef, ViewRef, DefinitionBase } from '../../../addressing/index.js';
1
+ import type { CoreRef, ClassRef, FunctionRef, PolicyRef, ViewRef, DefinitionBase, MethodAddress } from '../../../addressing/index.js';
2
2
  export type PolicyPatternTerm = {
3
3
  readonly kind: 'subject';
4
4
  } | {
@@ -10,14 +10,49 @@ export type PolicyPatternTerm = {
10
10
  } | {
11
11
  readonly kind: 'variable';
12
12
  readonly id: number;
13
+ } | {
14
+ readonly kind: 'ref';
15
+ readonly ref: PolicyObjectRef;
13
16
  };
14
- export interface PolicyVariable {
17
+ /** Identity equality; both terms must resolve to one valid Node. */
18
+ export interface PolicySameNode<Term> {
19
+ readonly sameNode: {
20
+ readonly left: Term;
21
+ readonly right: Term;
22
+ };
23
+ }
24
+ export interface ExactPolicyVariable {
15
25
  readonly variable: {
16
26
  readonly kind: 'variable';
17
27
  readonly id: number;
18
28
  };
19
29
  readonly class: ClassRef;
20
30
  }
31
+ export interface SelectedPolicyVariable {
32
+ readonly variable: {
33
+ readonly kind: 'variable';
34
+ readonly id: number;
35
+ };
36
+ readonly selector: {
37
+ readonly kind: 'any';
38
+ } | {
39
+ readonly kind: 'satisfies';
40
+ readonly class: ClassRef;
41
+ };
42
+ }
43
+ /**
44
+ * An existential Node binding. The class-bearing legacy form is deliberately retained as the
45
+ * canonical exact selector so persisted V1 DomainSchema documents keep their original meaning.
46
+ */
47
+ export type PolicyVariable = ExactPolicyVariable | SelectedPolicyVariable;
48
+ export type PolicyVariableSelector = {
49
+ readonly kind: 'exact';
50
+ readonly class: ClassRef;
51
+ } | SelectedPolicyVariable['selector'];
52
+ /** Resolve the semantic selector while preserving the legacy exact wire representation. */
53
+ export declare function policyVariableSelector(variable: PolicyVariable): PolicyVariableSelector;
54
+ /** Return the selector's referenced Class, when it has one. */
55
+ export declare function policyVariableClass(variable: PolicyVariable): ClassRef | undefined;
21
56
  export interface PolicyRepeat {
22
57
  readonly min: number;
23
58
  readonly max: number;
@@ -28,7 +63,7 @@ export interface PolicyEdgePattern {
28
63
  readonly target: PolicyPatternTerm;
29
64
  readonly repeat?: PolicyRepeat;
30
65
  }
31
- export type PolicyPatternExpression = PolicyEdgePattern | {
66
+ export type PolicyPatternExpression = PolicyEdgePattern | PolicySameNode<PolicyPatternTerm> | {
32
67
  readonly exists: {
33
68
  readonly nodes: readonly PolicyVariable[];
34
69
  readonly where: PolicyPatternExpression;
@@ -50,7 +85,33 @@ export interface PolicyDefinition extends DefinitionBase<PolicyRef> {
50
85
  readonly description?: string;
51
86
  }
52
87
  /** Local Domain members whose installed projection resolves through one exact member Path. */
53
- export type PolicyObjectRef = ClassRef | FunctionRef | PolicyRef | ViewRef | CoreRef;
88
+ export type PolicyObjectRef = ClassRef | FunctionRef | PolicyRef | ViewRef | CoreRef | MethodAddress;
89
+ /** Exact projected identity, including Class-owned Method declarations. */
90
+ export declare function policyObjectKey(ref: PolicyObjectRef): string;
91
+ export declare function policyObjectOrigin(ref: PolicyObjectRef): string;
92
+ export declare function projectedMemberClass(ref: Exclude<PolicyObjectRef, CoreRef>): ClassRef;
93
+ /**
94
+ * One Class observation slot: a named Policy, or `false`, the rule no caller satisfies. Its other
95
+ * value has no spelling there: an absent observation Policy already means `true`.
96
+ */
97
+ export type ClassPolicy = PolicyRef | false;
98
+ /** What a Node Class rule may check: the observed Node, or one exact projected member. */
99
+ export type ClassRuleObject = Extract<PolicyCheckObject, {
100
+ readonly kind: 'self' | 'ref';
101
+ }>;
102
+ /**
103
+ * Policy checks deciding one Node Class observation. `self` is the observed Node; a `ref` object
104
+ * is the same Node for every candidate. A lone check of `self` is spelled as its Policy reference.
105
+ */
106
+ export type ClassRuleChecks = PolicyCheckExpression<PolicyRef, ClassRuleObject>;
107
+ /** One Node Class observation slot: a Class Policy, or Policy checks over the observed Node. */
108
+ export type NodeClassPolicy = ClassPolicy | ClassRuleChecks;
109
+ export declare function isClassRuleChecks(value: ClassPolicy | ClassRuleChecks | undefined): value is ClassRuleChecks;
110
+ /**
111
+ * Whether every way Policy checks can hold passes through a check, so that the caller decides each
112
+ * admission. `sameNode` compares two objects and names no caller.
113
+ */
114
+ export declare function checksNameTheCaller(value: PolicyCheckExpression<unknown, unknown>): boolean;
54
115
  export type PolicyCheckObject = {
55
116
  readonly kind: 'self';
56
117
  } | {
@@ -64,7 +125,7 @@ export type PolicyCheckObject = {
64
125
  export type PolicyCheckExpression<Policy = PolicyRef, Object = PolicyCheckObject> = {
65
126
  readonly check: Policy;
66
127
  readonly object: Object;
67
- } | {
128
+ } | PolicySameNode<Object> | {
68
129
  readonly allOf: readonly [
69
130
  PolicyCheckExpression<Policy, Object>,
70
131
  ...PolicyCheckExpression<Policy, Object>[]
@@ -75,3 +136,8 @@ export type PolicyCheckExpression<Policy = PolicyRef, Object = PolicyCheckObject
75
136
  ...PolicyCheckExpression<Policy, Object>[]
76
137
  ];
77
138
  };
139
+ /**
140
+ * One authorized callable's caller rule: Policy checks, or `true`, the rule every caller satisfies.
141
+ * Its other value has no spelling there: an absent callable Policy already means `false`.
142
+ */
143
+ export type CallablePolicy = PolicyCheckExpression | true;
@@ -1 +1,52 @@
1
- export {};
1
+ /** Resolve the semantic selector while preserving the legacy exact wire representation. */
2
+ export function policyVariableSelector(variable) {
3
+ return 'class' in variable ? { kind: 'exact', class: variable.class } : variable.selector;
4
+ }
5
+ /** Return the selector's referenced Class, when it has one. */
6
+ export function policyVariableClass(variable) {
7
+ const selector = policyVariableSelector(variable);
8
+ return selector.kind === 'any' ? undefined : selector.class;
9
+ }
10
+ /** Exact projected identity, including Class-owned Method declarations. */
11
+ export function policyObjectKey(ref) {
12
+ return ref.kind === 'method'
13
+ ? `${ref.owner.origin}:class.${ref.owner.name}.method.${ref.name}`
14
+ : `${ref.origin}:${ref.kind}.${ref.name}`;
15
+ }
16
+ export function policyObjectOrigin(ref) {
17
+ return ref.kind === 'method' ? ref.owner.origin : ref.origin;
18
+ }
19
+ /**
20
+ * The Kernel declaration Class each projected member materializes as. A Core Node is absent: it
21
+ * keeps the concrete Class its own Domain authored, which only that Domain's schema can resolve.
22
+ */
23
+ const PROJECTED_MEMBER_CLASSES = Object.freeze({
24
+ class: kernelClassRef('Class'),
25
+ function: kernelClassRef('Function'),
26
+ method: kernelClassRef('Function'),
27
+ policy: kernelClassRef('Policy'),
28
+ view: kernelClassRef('View'),
29
+ });
30
+ export function projectedMemberClass(ref) {
31
+ return PROJECTED_MEMBER_CLASSES[ref.kind];
32
+ }
33
+ function kernelClassRef(name) {
34
+ return Object.freeze({ origin: 'kernel.astrale.ai', kind: 'class', name });
35
+ }
36
+ export function isClassRuleChecks(value) {
37
+ return (typeof value === 'object' &&
38
+ ('check' in value || 'sameNode' in value || 'allOf' in value || 'anyOf' in value));
39
+ }
40
+ /**
41
+ * Whether every way Policy checks can hold passes through a check, so that the caller decides each
42
+ * admission. `sameNode` compares two objects and names no caller.
43
+ */
44
+ export function checksNameTheCaller(value) {
45
+ if ('check' in value)
46
+ return true;
47
+ if ('sameNode' in value)
48
+ return false;
49
+ if ('allOf' in value)
50
+ return value.allOf.some(checksNameTheCaller);
51
+ return value.anyOf.every(checksNameTheCaller);
52
+ }
@@ -1,4 +1,15 @@
1
- import type { PolicyCheckExpression, PolicyExpression, PolicyPatternExpression } from '../model/policy.js';
1
+ import type { NodeClassPolicy, PolicyCheckExpression, PolicyExpression, PolicyPatternExpression } from '../model/policy.js';
2
2
  export declare function normalizePolicyExpression(value: PolicyExpression): PolicyExpression;
3
+ /**
4
+ * The fixed point of the single pass: a Pattern the single pass reproduces is returned unchanged,
5
+ * so the canonical form of every Pattern that was already stable keeps its bytes.
6
+ */
3
7
  export declare function normalizePolicyPattern(value: PolicyPatternExpression): PolicyPatternExpression;
8
+ /**
9
+ * The one spelling of a Node Class observation rule: normalized Policy checks without a composition
10
+ * of one operand, or the Policy that a lone check of `self` names, which is how a Class has always
11
+ * declared one. Callable checks keep their compositions of one operand: their revisions predate
12
+ * this rule.
13
+ */
14
+ export declare function normalizeClassRule(value: NodeClassPolicy): NodeClassPolicy;
4
15
  export declare function normalizePolicyChecks(value: PolicyCheckExpression): PolicyCheckExpression;
@@ -1,6 +1,6 @@
1
1
  import { json } from '@astrale-os/kernel-dsl/value';
2
2
  import { definitionRefIndex, compareDefinitionRefs } from '../../../addressing/ordering.js';
3
- const textEncoder = new TextEncoder();
3
+ import { isClassRuleChecks, policyObjectKey, policyVariableSelector } from '../model/policy.js';
4
4
  export function normalizePolicyExpression(value) {
5
5
  if ('match' in value) {
6
6
  return { match: normalizePolicyPattern(value.match) };
@@ -10,13 +10,70 @@ export function normalizePolicyExpression(value) {
10
10
  }
11
11
  return { anyOf: uniqueRefs(value.anyOf) };
12
12
  }
13
+ /**
14
+ * Passes after the first, while one still changes the Pattern. A pass numbers variables by the
15
+ * operands as written, then merges duplicate operands and flattens nested ones, so its result can
16
+ * number differently when normalized again; the next pass numbers that result by itself. One
17
+ * further pass reached the fixed point on every Pattern tested, the other is margin, and a
18
+ * Pattern still changing keeps its last pass rather than failing.
19
+ */
20
+ const SETTLING_PASSES = 2;
21
+ /**
22
+ * The fixed point of the single pass: a Pattern the single pass reproduces is returned unchanged,
23
+ * so the canonical form of every Pattern that was already stable keeps its bytes.
24
+ */
13
25
  export function normalizePolicyPattern(value) {
26
+ let current = normalizePatternOnce(value);
27
+ let encoding = json.serialize(current);
28
+ for (let pass = 0; pass < SETTLING_PASSES; pass++) {
29
+ const next = normalizePatternOnce(current);
30
+ const nextEncoding = json.serialize(next);
31
+ if (nextEncoding === encoding)
32
+ return current;
33
+ current = next;
34
+ encoding = nextEncoding;
35
+ }
36
+ return current;
37
+ }
38
+ function normalizePatternOnce(value) {
14
39
  const rewritten = rewriteVariables(value, canonicalVariableIds(value));
15
40
  return normalizePatternNode(rewritten);
16
41
  }
42
+ /**
43
+ * The one spelling of a Node Class observation rule: normalized Policy checks without a composition
44
+ * of one operand, or the Policy that a lone check of `self` names, which is how a Class has always
45
+ * declared one. Callable checks keep their compositions of one operand: their revisions predate
46
+ * this rule.
47
+ */
48
+ export function normalizeClassRule(value) {
49
+ if (!isClassRuleChecks(value))
50
+ return value;
51
+ const checks = unwrapSingleOperands(normalizePolicyChecks(value));
52
+ return 'check' in checks && checks.object.kind === 'self' ? checks.check : checks;
53
+ }
54
+ /** Replace each composition of one operand by that operand, merging what it then nests. */
55
+ function unwrapSingleOperands(value) {
56
+ if ('check' in value || 'sameNode' in value)
57
+ return value;
58
+ const all = 'allOf' in value;
59
+ const children = uniqueJson((all ? value.allOf : value.anyOf).flatMap((child) => {
60
+ const unwrapped = unwrapSingleOperands(child);
61
+ if (all && 'allOf' in unwrapped)
62
+ return unwrapped.allOf;
63
+ if (!all && 'anyOf' in unwrapped)
64
+ return unwrapped.anyOf;
65
+ return [unwrapped];
66
+ }));
67
+ if (children.length === 1)
68
+ return children[0];
69
+ const operands = policyCheckComposition(children);
70
+ return all ? { allOf: operands } : { anyOf: operands };
71
+ }
17
72
  export function normalizePolicyChecks(value) {
18
73
  if ('check' in value)
19
74
  return value;
75
+ if ('sameNode' in value)
76
+ return { sameNode: normalizeEquality(value.sameNode) };
20
77
  if ('allOf' in value) {
21
78
  const children = value.allOf.flatMap((child) => {
22
79
  const normalized = normalizePolicyChecks(child);
@@ -36,6 +93,8 @@ function policyCheckComposition(values) {
36
93
  return values;
37
94
  }
38
95
  function normalizePatternNode(value) {
96
+ if ('sameNode' in value)
97
+ return { sameNode: normalizeEquality(value.sameNode) };
39
98
  if (isEdge(value)) {
40
99
  const repeat = value.repeat;
41
100
  if (repeat?.min === 1 && repeat.max === 1) {
@@ -67,24 +126,34 @@ function normalizePatternNode(value) {
67
126
  }
68
127
  function canonicalVariableIds(value) {
69
128
  const declarations = new Map();
70
- collectDeclarations(value, declarations);
71
- const colors = new Map(declarations);
129
+ const depths = new Map();
130
+ collectDeclarations(value, declarations, depths);
131
+ const uses = new Map([...declarations.keys()].map((id) => [id, []]));
132
+ collectUses(value, uses);
133
+ let colors = declarations;
134
+ // Color refinement. Each round names a variable by its declaration and the sorted colors of its
135
+ // uses, then replaces every name by its fixed-width rank among the round's names. Ranks keep the
136
+ // names' byte order, so a round decides what it would decide over uncompressed names, while a
137
+ // name stays linear in its variable's degree instead of embedding every neighbour's name. A
138
+ // round that reproduces its input is a fixed point of the next ones.
72
139
  for (let iteration = 0; iteration < declarations.size + 1; iteration++) {
73
- const next = new Map();
74
- for (const id of declarations.keys()) {
75
- const uses = [];
76
- collectUses(value, id, colors, uses);
77
- uses.sort(compareUtf8Bytes);
78
- next.set(id, `${declarations.get(id) ?? ''}|${uses.join('|')}`);
79
- }
140
+ const next = rank(new Map([...uses].map(([id, list]) => {
141
+ const named = list.map(([prefix, term]) => `${prefix}${termColor(term, colors)}`);
142
+ return [id, `${declarations.get(id) ?? ''}|${named.sort(compareUtf8Bytes).join('|')}`];
143
+ })));
80
144
  if ([...next].every(([id, color]) => colors.get(id) === color))
81
145
  break;
82
- colors.clear();
83
- for (const [id, color] of next)
84
- colors.set(id, color);
146
+ colors = next;
85
147
  }
148
+ // Colors ignore where a variable is declared, so two variables can tie on color although
149
+ // different `exists` declare them, and which of them is numbered first decides which `exists`
150
+ // declares the smaller id. Their declaration depth tells them apart where it differs: operands of
151
+ // equal signature are ordered by their signature over depth-scoped colors before authored order,
152
+ // and the final order compares depth before the authored id (decision
153
+ // `policy-pattern-canonical-ties`). Both keys only order what color and first use leave tied.
154
+ const scoped = new Map([...colors].map(([id, color]) => [id, `${color}@${depths.get(id) ?? 0}`]));
86
155
  const firstUse = new Map();
87
- collectFirstUseKeys(value, colors, firstUse);
156
+ collectFirstUseKeys(value, colors, scoped, firstUse);
88
157
  const ordered = [...declarations.keys()].sort((left, right) => {
89
158
  const byColor = compareUtf8Bytes(colors.get(left) ?? '', colors.get(right) ?? '');
90
159
  if (byColor !== 0)
@@ -92,49 +161,80 @@ function canonicalVariableIds(value) {
92
161
  const byUse = compareUtf8Bytes(firstUse.get(left) ?? '', firstUse.get(right) ?? '');
93
162
  if (byUse !== 0)
94
163
  return byUse;
95
- // A remaining tie is an automorphic binder class: assigning either first
96
- // yields the same recursively sorted canonical Pattern.
164
+ const byDepth = (depths.get(left) ?? 0) - (depths.get(right) ?? 0);
165
+ if (byDepth !== 0)
166
+ return byDepth;
167
+ // A remaining tie keeps the authored order of the ids: such variables were interchangeable in
168
+ // every admissible Pattern checked (`__tests__/canonical.test.ts`).
97
169
  return left - right;
98
170
  });
99
171
  return new Map(ordered.map((id, index) => [id, index]));
100
172
  }
101
- function collectDeclarations(value, result) {
173
+ /** Each declared variable's selector signature and the number of `exists` around its declaration. */
174
+ function collectDeclarations(value, result, depths, depth = 0) {
102
175
  if ('exists' in value) {
103
176
  for (const node of value.exists.nodes) {
104
- result.set(node.variable.id, definitionRefIndex(node.class));
177
+ result.set(node.variable.id, selectorSignature(node));
178
+ depths.set(node.variable.id, depth + 1);
105
179
  }
106
- collectDeclarations(value.exists.where, result);
180
+ collectDeclarations(value.exists.where, result, depths, depth + 1);
107
181
  return;
108
182
  }
109
183
  if ('allOf' in value)
110
184
  for (const child of value.allOf)
111
- collectDeclarations(child, result);
185
+ collectDeclarations(child, result, depths, depth);
112
186
  if ('anyOf' in value)
113
187
  for (const child of value.anyOf)
114
- collectDeclarations(child, result);
188
+ collectDeclarations(child, result, depths, depth);
115
189
  }
116
- function collectUses(value, target, colors, result) {
190
+ function collectUses(value, result) {
191
+ if ('sameNode' in value) {
192
+ const { left, right } = value.sameNode;
193
+ if (left.kind === 'variable')
194
+ result.get(left.id)?.push(['same:', right]);
195
+ if (right.kind === 'variable')
196
+ result.get(right.id)?.push(['same:', left]);
197
+ return;
198
+ }
117
199
  if (isEdge(value)) {
118
- if (value.source.kind === 'variable' && value.source.id === target) {
119
- result.push(`s:${definitionRefIndex(value.class)}:${termColor(value.target, colors)}`);
120
- }
121
- if (value.target.kind === 'variable' && value.target.id === target) {
122
- result.push(`t:${definitionRefIndex(value.class)}:${termColor(value.source, colors)}`);
123
- }
200
+ const edge = definitionRefIndex(value.class);
201
+ if (value.source.kind === 'variable')
202
+ result.get(value.source.id)?.push([`s:${edge}:`, value.target]);
203
+ if (value.target.kind === 'variable')
204
+ result.get(value.target.id)?.push([`t:${edge}:`, value.source]);
124
205
  return;
125
206
  }
126
207
  if ('exists' in value)
127
- return collectUses(value.exists.where, target, colors, result);
208
+ return collectUses(value.exists.where, result);
128
209
  const children = 'allOf' in value ? value.allOf : value.anyOf;
129
210
  for (const child of children)
130
- collectUses(child, target, colors, result);
211
+ collectUses(child, result);
212
+ }
213
+ function rank(names) {
214
+ const distinct = [...new Set(names.values())].sort(compareUtf8Bytes);
215
+ const width = String(distinct.length).length;
216
+ const ranks = new Map(distinct.map((name, index) => [name, String(index).padStart(width, '0')]));
217
+ return new Map([...names].map(([id, name]) => [id, ranks.get(name) ?? '']));
131
218
  }
132
219
  function termColor(term, colors) {
133
220
  if (term.kind === 'variable')
134
221
  return `variable:${colors.get(term.id) ?? '?'}`;
222
+ if (term.kind === 'ref')
223
+ return `ref:${term.ref.kind === 'method' ? policyObjectKey(term.ref) : definitionRefIndex(term.ref)}`;
135
224
  return term.kind;
136
225
  }
137
- function collectFirstUseKeys(value, colors, result, prefix = '$') {
226
+ function collectFirstUseKeys(value, colors, scoped, result, prefix = '$') {
227
+ if ('sameNode' in value) {
228
+ for (const term of [value.sameNode.left, value.sameNode.right]) {
229
+ if (term.kind !== 'variable')
230
+ continue;
231
+ const key = `${prefix}:same`;
232
+ const current = result.get(term.id);
233
+ if (current === undefined || key < current)
234
+ result.set(term.id, key);
235
+ }
236
+ return;
237
+ }
138
238
  if (isEdge(value)) {
139
239
  for (const [position, term] of [
140
240
  ['source', value.source],
@@ -150,15 +250,19 @@ function collectFirstUseKeys(value, colors, result, prefix = '$') {
150
250
  return;
151
251
  }
152
252
  if ('exists' in value) {
153
- collectFirstUseKeys(value.exists.where, colors, result, `${prefix}:exists`);
253
+ collectFirstUseKeys(value.exists.where, colors, scoped, result, `${prefix}:exists`);
154
254
  return;
155
255
  }
156
256
  const key = 'allOf' in value ? 'allOf' : 'anyOf';
157
257
  const operands = 'allOf' in value ? value.allOf : value.anyOf;
158
- const children = [...operands].sort((left, right) => compareUtf8Bytes(patternSignature(left, colors), patternSignature(right, colors)));
159
- children.forEach((child, index) => collectFirstUseKeys(child, colors, result, `${prefix}:${key}:${index}`));
258
+ const children = operands
259
+ .map((child) => [patternSignature(child, colors), patternSignature(child, scoped), child])
260
+ .sort(([left, leftScoped], [right, rightScoped]) => compareUtf8Bytes(left, right) || compareUtf8Bytes(leftScoped, rightScoped));
261
+ children.forEach(([, , child], index) => collectFirstUseKeys(child, colors, scoped, result, `${prefix}:${key}:${index}`));
160
262
  }
161
263
  function patternSignature(value, colors) {
264
+ if ('sameNode' in value)
265
+ return `same:${[termColor(value.sameNode.left, colors), termColor(value.sameNode.right, colors)].sort(compareUtf8Bytes).join(':')}`;
162
266
  if (isEdge(value)) {
163
267
  return `edge:${definitionRefIndex(value.class)}:${termColor(value.source, colors)}:${termColor(value.target, colors)}:${value.repeat?.min ?? 1}:${value.repeat?.max ?? 1}`;
164
268
  }
@@ -176,6 +280,13 @@ function patternSignature(value, colors) {
176
280
  .join('|')}`;
177
281
  }
178
282
  function rewriteVariables(value, ids) {
283
+ if ('sameNode' in value)
284
+ return {
285
+ sameNode: {
286
+ left: rewriteTerm(value.sameNode.left, ids),
287
+ right: rewriteTerm(value.sameNode.right, ids),
288
+ },
289
+ };
179
290
  if (isEdge(value)) {
180
291
  return {
181
292
  ...value,
@@ -186,10 +297,15 @@ function rewriteVariables(value, ids) {
186
297
  if ('exists' in value) {
187
298
  return {
188
299
  exists: {
189
- nodes: value.exists.nodes.map((node) => ({
190
- variable: { kind: 'variable', id: ids.get(node.variable.id) ?? node.variable.id },
191
- class: node.class,
192
- })),
300
+ nodes: value.exists.nodes.map((node) => {
301
+ const variable = {
302
+ kind: 'variable',
303
+ id: ids.get(node.variable.id) ?? node.variable.id,
304
+ };
305
+ return 'class' in node
306
+ ? { variable, class: node.class }
307
+ : { variable, selector: node.selector };
308
+ }),
193
309
  where: rewriteVariables(value.exists.where, ids),
194
310
  },
195
311
  };
@@ -198,6 +314,10 @@ function rewriteVariables(value, ids) {
198
314
  return { allOf: value.allOf.map((child) => rewriteVariables(child, ids)) };
199
315
  return { anyOf: value.anyOf.map((child) => rewriteVariables(child, ids)) };
200
316
  }
317
+ function selectorSignature(node) {
318
+ const selector = policyVariableSelector(node);
319
+ return selector.kind === 'any' ? 'any' : `${selector.kind}:${definitionRefIndex(selector.class)}`;
320
+ }
201
321
  function rewriteTerm(value, ids) {
202
322
  return value.kind === 'variable' ? { kind: 'variable', id: ids.get(value.id) ?? value.id } : value;
203
323
  }
@@ -211,16 +331,30 @@ function uniqueJson(values) {
211
331
  .sort(([left], [right]) => compareUtf8Bytes(left, right))
212
332
  .map(([, value]) => value);
213
333
  }
334
+ /**
335
+ * UTF-8 byte order without encoding: it is code-point order, which UTF-16 code units already follow
336
+ * except that surrogates (U+10000 and above) sort after U+E000–U+FFFF.
337
+ */
214
338
  function compareUtf8Bytes(left, right) {
215
- const a = textEncoder.encode(left);
216
- const b = textEncoder.encode(right);
217
- const length = Math.min(a.length, b.length);
339
+ const length = Math.min(left.length, right.length);
218
340
  for (let index = 0; index < length; index++) {
219
- if (a[index] !== b[index])
220
- return (a[index] ?? 0) - (b[index] ?? 0);
341
+ const a = left.charCodeAt(index);
342
+ const b = right.charCodeAt(index);
343
+ if (a !== b)
344
+ return codePointOrder(a) - codePointOrder(b);
221
345
  }
222
- return a.length - b.length;
346
+ return left.length - right.length;
347
+ }
348
+ function codePointOrder(unit) {
349
+ if (unit >= 0xd800 && unit <= 0xdfff)
350
+ return unit + 0x2000;
351
+ return unit >= 0xe000 ? unit - 0x800 : unit;
223
352
  }
224
353
  function isEdge(value) {
225
354
  return 'source' in value;
226
355
  }
356
+ function normalizeEquality(value) {
357
+ return compareUtf8Bytes(json.serialize(value.left), json.serialize(value.right)) <= 0
358
+ ? value
359
+ : { left: value.right, right: value.left };
360
+ }
@@ -0,0 +1,3 @@
1
+ export { stateMachine } from './machine.js';
2
+ export type { EventOf, StateMachine, StateOf } from './machine.js';
3
+ export type { StateTopology } from './topology.js';
@@ -0,0 +1 @@
1
+ export { stateMachine } from './machine.js';