semantifold 0.3.0 → 0.4.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 (297) hide show
  1. package/README.md +58 -15
  2. package/build/index.d.ts +48 -2
  3. package/build/index.d.ts.map +1 -1
  4. package/build/index.js +57 -8
  5. package/build/src/artifact-path.d.ts +23 -1
  6. package/build/src/artifact-path.d.ts.map +1 -1
  7. package/build/src/artifact-path.js +45 -3
  8. package/build/src/artifacts.d.ts.map +1 -1
  9. package/build/src/artifacts.js +66 -1
  10. package/build/src/backends/c-validation.d.ts.map +1 -1
  11. package/build/src/backends/c-validation.js +7 -3
  12. package/build/src/backends/cpp-validation.d.ts.map +1 -1
  13. package/build/src/backends/cpp-validation.js +7 -3
  14. package/build/src/backends/csharp.js +7 -1
  15. package/build/src/backends/dart-runtime.d.ts +2 -0
  16. package/build/src/backends/dart-runtime.d.ts.map +1 -0
  17. package/build/src/backends/dart-runtime.js +41 -0
  18. package/build/src/backends/dart.d.ts +20 -0
  19. package/build/src/backends/dart.d.ts.map +1 -0
  20. package/build/src/backends/dart.js +321 -0
  21. package/build/src/backends/effects.d.ts +60 -0
  22. package/build/src/backends/effects.d.ts.map +1 -0
  23. package/build/src/backends/effects.js +746 -0
  24. package/build/src/backends/go.js +18 -4
  25. package/build/src/backends/identifiers.d.ts +36 -4
  26. package/build/src/backends/identifiers.d.ts.map +1 -1
  27. package/build/src/backends/identifiers.js +154 -10
  28. package/build/src/backends/index.d.ts.map +1 -1
  29. package/build/src/backends/index.js +27 -4
  30. package/build/src/backends/ios.d.ts +68 -0
  31. package/build/src/backends/ios.d.ts.map +1 -0
  32. package/build/src/backends/ios.js +1503 -0
  33. package/build/src/backends/java.d.ts.map +1 -1
  34. package/build/src/backends/java.js +429 -36
  35. package/build/src/backends/javascript.d.ts +6 -0
  36. package/build/src/backends/javascript.d.ts.map +1 -1
  37. package/build/src/backends/javascript.js +380 -24
  38. package/build/src/backends/kotlin-runtime.d.ts +3 -0
  39. package/build/src/backends/kotlin-runtime.d.ts.map +1 -0
  40. package/build/src/backends/kotlin-runtime.js +29 -0
  41. package/build/src/backends/kotlin.d.ts +23 -0
  42. package/build/src/backends/kotlin.d.ts.map +1 -0
  43. package/build/src/backends/kotlin.js +136 -0
  44. package/build/src/backends/native-validation.d.ts +2 -2
  45. package/build/src/backends/native-validation.d.ts.map +1 -1
  46. package/build/src/backends/native-validation.js +2 -2
  47. package/build/src/backends/ordered-expressions.d.ts.map +1 -1
  48. package/build/src/backends/ordered-expressions.js +39 -7
  49. package/build/src/backends/php-stdlib-support.d.ts +19 -0
  50. package/build/src/backends/php-stdlib-support.d.ts.map +1 -0
  51. package/build/src/backends/php-stdlib-support.js +227 -0
  52. package/build/src/backends/php.d.ts.map +1 -1
  53. package/build/src/backends/php.js +448 -33
  54. package/build/src/backends/program.d.ts +81 -0
  55. package/build/src/backends/program.d.ts.map +1 -0
  56. package/build/src/backends/program.js +1308 -0
  57. package/build/src/backends/python.js +7 -1
  58. package/build/src/backends/ruby.d.ts.map +1 -1
  59. package/build/src/backends/ruby.js +310 -24
  60. package/build/src/backends/rust-runtime.d.ts +7 -0
  61. package/build/src/backends/rust-runtime.d.ts.map +1 -0
  62. package/build/src/backends/rust-runtime.js +32 -0
  63. package/build/src/backends/rust-validation.d.ts +9 -0
  64. package/build/src/backends/rust-validation.d.ts.map +1 -0
  65. package/build/src/backends/rust-validation.js +78 -0
  66. package/build/src/backends/rust.d.ts +24 -0
  67. package/build/src/backends/rust.d.ts.map +1 -0
  68. package/build/src/backends/rust.js +344 -0
  69. package/build/src/backends/scalars.d.ts +14 -6
  70. package/build/src/backends/scalars.d.ts.map +1 -1
  71. package/build/src/backends/scalars.js +167 -17
  72. package/build/src/backends/shared.d.ts +23 -4
  73. package/build/src/backends/shared.d.ts.map +1 -1
  74. package/build/src/backends/shared.js +2158 -62
  75. package/build/src/backends/stdlib-support.d.ts +14 -0
  76. package/build/src/backends/stdlib-support.d.ts.map +1 -0
  77. package/build/src/backends/stdlib-support.js +237 -0
  78. package/build/src/backends/swift-runtime.d.ts +3 -0
  79. package/build/src/backends/swift-runtime.d.ts.map +1 -0
  80. package/build/src/backends/swift-runtime.js +14 -0
  81. package/build/src/backends/swift.d.ts +8 -0
  82. package/build/src/backends/swift.d.ts.map +1 -0
  83. package/build/src/backends/swift.js +127 -0
  84. package/build/src/backends/typescript.d.ts.map +1 -1
  85. package/build/src/backends/typescript.js +344 -24
  86. package/build/src/backends/wasm.d.ts +43 -0
  87. package/build/src/backends/wasm.d.ts.map +1 -0
  88. package/build/src/backends/wasm.js +2164 -0
  89. package/build/src/backends/writer.d.ts +235 -4
  90. package/build/src/backends/writer.d.ts.map +1 -1
  91. package/build/src/backends/writer.js +468 -3
  92. package/build/src/diagnostic.d.ts +4 -3
  93. package/build/src/diagnostic.d.ts.map +1 -1
  94. package/build/src/diagnostic.js +5 -3
  95. package/build/src/frontends/c.d.ts.map +1 -1
  96. package/build/src/frontends/c.js +5 -3
  97. package/build/src/frontends/cpp.d.ts.map +1 -1
  98. package/build/src/frontends/cpp.js +5 -3
  99. package/build/src/frontends/csharp.d.ts.map +1 -1
  100. package/build/src/frontends/csharp.js +7 -3
  101. package/build/src/frontends/dart.d.ts +10 -0
  102. package/build/src/frontends/dart.d.ts.map +1 -0
  103. package/build/src/frontends/dart.js +913 -0
  104. package/build/src/frontends/index.d.ts +3 -1
  105. package/build/src/frontends/index.d.ts.map +1 -1
  106. package/build/src/frontends/index.js +15 -5
  107. package/build/src/frontends/java.d.ts +110 -1
  108. package/build/src/frontends/java.d.ts.map +1 -1
  109. package/build/src/frontends/java.js +1725 -70
  110. package/build/src/frontends/javascript-typescript.d.ts +69 -1
  111. package/build/src/frontends/javascript-typescript.d.ts.map +1 -1
  112. package/build/src/frontends/javascript-typescript.js +1825 -93
  113. package/build/src/frontends/kotlin.d.ts +10 -0
  114. package/build/src/frontends/kotlin.d.ts.map +1 -0
  115. package/build/src/frontends/kotlin.js +685 -0
  116. package/build/src/frontends/php.d.ts +118 -1
  117. package/build/src/frontends/php.d.ts.map +1 -1
  118. package/build/src/frontends/php.js +1583 -76
  119. package/build/src/frontends/program.d.ts +74 -0
  120. package/build/src/frontends/program.d.ts.map +1 -0
  121. package/build/src/frontends/program.js +989 -0
  122. package/build/src/frontends/ruby.d.ts +68 -1
  123. package/build/src/frontends/ruby.d.ts.map +1 -1
  124. package/build/src/frontends/ruby.js +1446 -101
  125. package/build/src/frontends/rust-parser.d.ts +11 -0
  126. package/build/src/frontends/rust-parser.d.ts.map +1 -0
  127. package/build/src/frontends/rust-parser.js +15 -0
  128. package/build/src/frontends/rust.d.ts +14 -0
  129. package/build/src/frontends/rust.d.ts.map +1 -0
  130. package/build/src/frontends/rust.js +715 -0
  131. package/build/src/frontends/scalars.d.ts +10 -0
  132. package/build/src/frontends/scalars.d.ts.map +1 -1
  133. package/build/src/frontends/scalars.js +28 -2
  134. package/build/src/frontends/swift.d.ts +10 -0
  135. package/build/src/frontends/swift.d.ts.map +1 -0
  136. package/build/src/frontends/swift.js +860 -0
  137. package/build/src/frontends/types.d.ts +186 -0
  138. package/build/src/frontends/types.d.ts.map +1 -0
  139. package/build/src/frontends/types.js +634 -0
  140. package/build/src/language-registry.d.ts +46 -4
  141. package/build/src/language-registry.d.ts.map +1 -1
  142. package/build/src/language-registry.js +167 -13
  143. package/build/src/mapping.d.ts +2 -2
  144. package/build/src/mapping.d.ts.map +1 -1
  145. package/build/src/mapping.js +31 -10
  146. package/build/src/semantic/capabilities.d.ts +66 -0
  147. package/build/src/semantic/capabilities.d.ts.map +1 -0
  148. package/build/src/semantic/capabilities.js +649 -0
  149. package/build/src/semantic/effects.d.ts +26 -0
  150. package/build/src/semantic/effects.d.ts.map +1 -0
  151. package/build/src/semantic/effects.js +764 -0
  152. package/build/src/semantic/generics.d.ts +23 -0
  153. package/build/src/semantic/generics.d.ts.map +1 -0
  154. package/build/src/semantic/generics.js +61 -0
  155. package/build/src/semantic/lifetime.d.ts +37 -0
  156. package/build/src/semantic/lifetime.d.ts.map +1 -0
  157. package/build/src/semantic/lifetime.js +527 -0
  158. package/build/src/semantic/provenance.d.ts +9 -2
  159. package/build/src/semantic/provenance.d.ts.map +1 -1
  160. package/build/src/semantic/provenance.js +462 -20
  161. package/build/src/semantic/scalars.d.ts +11 -0
  162. package/build/src/semantic/scalars.d.ts.map +1 -1
  163. package/build/src/semantic/scalars.js +16 -1
  164. package/build/src/semantic/stdlib.d.ts +254 -0
  165. package/build/src/semantic/stdlib.d.ts.map +1 -0
  166. package/build/src/semantic/stdlib.js +880 -0
  167. package/build/src/semantic/types.d.ts +2952 -202
  168. package/build/src/semantic/types.d.ts.map +1 -1
  169. package/build/src/semantic/types.js +688 -15
  170. package/build/src/semantic/validate.d.ts +85 -5
  171. package/build/src/semantic/validate.d.ts.map +1 -1
  172. package/build/src/semantic/validate.js +2576 -98
  173. package/build/src/stdlib-facades.d.ts +304 -0
  174. package/build/src/stdlib-facades.d.ts.map +1 -0
  175. package/build/src/stdlib-facades.js +1167 -0
  176. package/build/src/stdlib-negotiation.d.ts +69 -0
  177. package/build/src/stdlib-negotiation.d.ts.map +1 -0
  178. package/build/src/stdlib-negotiation.js +403 -0
  179. package/build/src/stdlib-providers.d.ts +72 -0
  180. package/build/src/stdlib-providers.d.ts.map +1 -0
  181. package/build/src/stdlib-providers.js +339 -0
  182. package/build/src/toolchains.d.ts +55 -1
  183. package/build/src/toolchains.d.ts.map +1 -1
  184. package/build/src/toolchains.js +15 -4
  185. package/docs/architecture.md +45 -13
  186. package/docs/dart.md +60 -0
  187. package/docs/goals.md +3 -3
  188. package/docs/ios.md +121 -0
  189. package/docs/kotlin.md +42 -0
  190. package/docs/language-support.md +231 -26
  191. package/docs/multi-file-modules.md +52 -0
  192. package/docs/parser-qualification.md +121 -8
  193. package/docs/plans/2026-09-05-standard-library-portability.md +10 -10
  194. package/docs/rust.md +88 -0
  195. package/docs/source-maps.md +15 -7
  196. package/docs/standard-library-portability.md +39 -8
  197. package/docs/swift.md +44 -0
  198. package/docs/testing.md +366 -4
  199. package/docs/webassembly.md +52 -0
  200. package/index.js +63 -8
  201. package/node_modules/semantifold-tree-sitter-legacy-internal/README.md +2 -2
  202. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/LICENSE +21 -0
  203. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/README.md +45 -0
  204. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/binding.gyp +30 -0
  205. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/binding.cc +20 -0
  206. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/binding_test.js +9 -0
  207. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/index.d.ts +28 -0
  208. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/bindings/node/index.js +11 -0
  209. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/grammar.js +1630 -0
  210. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/package.json +64 -0
  211. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/darwin-arm64/tree-sitter-rust.node +0 -0
  212. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/darwin-x64/tree-sitter-rust.node +0 -0
  213. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/linux-arm64/tree-sitter-rust.node +0 -0
  214. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/linux-x64/tree-sitter-rust.node +0 -0
  215. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/win32-arm64/tree-sitter-rust.node +0 -0
  216. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/prebuilds/win32-x64/tree-sitter-rust.node +0 -0
  217. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/highlights.scm +159 -0
  218. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/injections.scm +9 -0
  219. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/queries/tags.scm +60 -0
  220. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/grammar.json +9405 -0
  221. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/node-types.json +5399 -0
  222. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/parser.c +192569 -0
  223. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/scanner.c +393 -0
  224. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/alloc.h +54 -0
  225. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/array.h +290 -0
  226. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/src/tree_sitter/parser.h +266 -0
  227. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/tree-sitter-rust.wasm +0 -0
  228. package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-rust/tree-sitter.json +53 -0
  229. package/node_modules/semantifold-tree-sitter-legacy-internal/package.json +3 -2
  230. package/node_modules/semantifold-tree-sitter-legacy-internal/src/c.js +5 -4
  231. package/package.json +5 -2
  232. package/src/artifact-path.js +47 -2
  233. package/src/artifacts.js +67 -0
  234. package/src/backends/c-validation.js +6 -1
  235. package/src/backends/cpp-validation.js +6 -1
  236. package/src/backends/csharp.js +3 -0
  237. package/src/backends/dart-runtime.js +41 -0
  238. package/src/backends/dart.js +326 -0
  239. package/src/backends/effects.js +705 -0
  240. package/src/backends/go.js +14 -2
  241. package/src/backends/identifiers.js +160 -9
  242. package/src/backends/index.js +27 -2
  243. package/src/backends/ios.js +1612 -0
  244. package/src/backends/java.js +454 -36
  245. package/src/backends/javascript.js +389 -23
  246. package/src/backends/kotlin-runtime.js +29 -0
  247. package/src/backends/kotlin.js +141 -0
  248. package/src/backends/native-validation.js +1 -1
  249. package/src/backends/ordered-expressions.js +40 -6
  250. package/src/backends/php-stdlib-support.js +239 -0
  251. package/src/backends/php.js +469 -32
  252. package/src/backends/program.js +1407 -0
  253. package/src/backends/python.js +3 -0
  254. package/src/backends/ruby.js +326 -23
  255. package/src/backends/rust-runtime.js +34 -0
  256. package/src/backends/rust-validation.js +75 -0
  257. package/src/backends/rust.js +335 -0
  258. package/src/backends/scalars.js +141 -16
  259. package/src/backends/shared.js +2304 -124
  260. package/src/backends/stdlib-support.js +234 -0
  261. package/src/backends/swift-runtime.js +14 -0
  262. package/src/backends/swift.js +132 -0
  263. package/src/backends/typescript.js +349 -23
  264. package/src/backends/wasm.js +2208 -0
  265. package/src/backends/writer.js +520 -2
  266. package/src/diagnostic.js +4 -2
  267. package/src/frontends/c.js +4 -2
  268. package/src/frontends/cpp.js +4 -2
  269. package/src/frontends/csharp.js +4 -2
  270. package/src/frontends/dart.js +963 -0
  271. package/src/frontends/index.js +14 -4
  272. package/src/frontends/java.js +1977 -69
  273. package/src/frontends/javascript-typescript.js +2046 -102
  274. package/src/frontends/kotlin.js +713 -0
  275. package/src/frontends/php.js +1725 -79
  276. package/src/frontends/program.js +1062 -0
  277. package/src/frontends/ruby.js +1624 -98
  278. package/src/frontends/rust-parser.js +18 -0
  279. package/src/frontends/rust.js +714 -0
  280. package/src/frontends/scalars.js +31 -1
  281. package/src/frontends/swift.js +893 -0
  282. package/src/frontends/types.js +750 -0
  283. package/src/language-registry.js +172 -12
  284. package/src/mapping.js +33 -9
  285. package/src/semantic/capabilities.js +671 -0
  286. package/src/semantic/effects.js +737 -0
  287. package/src/semantic/generics.js +58 -0
  288. package/src/semantic/lifetime.js +517 -0
  289. package/src/semantic/provenance.js +412 -19
  290. package/src/semantic/scalars.js +17 -0
  291. package/src/semantic/stdlib.js +921 -0
  292. package/src/semantic/types.js +765 -14
  293. package/src/semantic/validate.js +2934 -209
  294. package/src/stdlib-facades.js +1211 -0
  295. package/src/stdlib-negotiation.js +446 -0
  296. package/src/stdlib-providers.js +377 -0
  297. package/src/toolchains.js +16 -3
@@ -0,0 +1,921 @@
1
+ // @ts-check
2
+
3
+ import {SemantifoldDiagnostic} from "../diagnostic.js"
4
+
5
+ const identityPattern = /^[a-z][a-z0-9.-]*$/u
6
+ const declarationNamePattern = /^[A-Za-z_][A-Za-z0-9_]*$/u
7
+ const scalarNames = new Set(["boolean", "integer", "string"])
8
+ const component = "(0|[1-9][0-9]*)"
9
+ const exactVersionPattern = new RegExp(`^${component}\\.${component}\\.${component}$`, "u")
10
+ const rangePattern = new RegExp(`^${component}(?:\\.${component}){0,2}$`, "u")
11
+ const semanticsValues = {
12
+ blocking: new Set(["synchronous"]),
13
+ close: new Set(["not-applicable", "use-after-close-fails", "repeated-close-fails"]),
14
+ eof: new Set(["not-applicable", "absent-value"]),
15
+ encoding: new Set(["not-applicable", "utf-8"]),
16
+ newline: new Set(["not-applicable", "strip-line-terminator", "retain-line-terminator", "append-lf-if-missing"]),
17
+ ownership: new Set(["not-applicable", "acquired", "borrowed", "consumed"]),
18
+ timeout: new Set(["none"])
19
+ }
20
+
21
+ /** @typedef {[number, number, number]} VersionTuple */
22
+ /** @typedef {{lower: VersionTuple, upper: VersionTuple | null}} VersionRange */
23
+ /** @typedef {{module: string, name: string}} CanonicalDeclarationReference */
24
+ /**
25
+ * @typedef StdlibContractOperation
26
+ * @property {{module: string, operation: string, range: VersionRange}[]} dependencies - Canonical operation dependencies.
27
+ * @property {["host"]} effects - Closed effect declaration.
28
+ * @property {"left-to-right"} evaluationOrder - Canonical argument evaluation order.
29
+ * @property {(string | CanonicalDeclarationReference)[]} failures - Declared failure names.
30
+ * @property {string} name - Operation name.
31
+ * @property {{name: string, type: string | CanonicalDeclarationReference}[]} parameters - Ordered parameters.
32
+ * @property {object} resourceFlow - Closed resource transition.
33
+ * @property {string | CanonicalDeclarationReference} returnType - Closed return type spelling.
34
+ * @property {Record<string, string>} semantics - Closed canonical semantics fields.
35
+ */
36
+ /**
37
+ * @typedef StdlibContractModule
38
+ * @property {{module: string, range: VersionRange}[]} dependencies - Versioned declaration dependencies.
39
+ * @property {{name: string}[]} failures - Ordered failure declarations.
40
+ * @property {string} identity - Canonical module identity.
41
+ * @property {StdlibContractOperation[]} operations - Ordered operation declarations.
42
+ * @property {{name: string}[]} resources - Ordered resource declarations.
43
+ * @property {string} version - Exact registered version.
44
+ */
45
+ /**
46
+ * @typedef StdlibContract
47
+ * @property {{module: string, range: VersionRange}[]} dependencies - Versioned declaration dependencies.
48
+ * @property {{name: string}[]} failures - Ordered failure declarations.
49
+ * @property {string} identity - Canonical module identity.
50
+ * @property {StdlibContractOperation[]} operations - Ordered operation declarations.
51
+ * @property {{name: string}[]} resources - Ordered resource declarations.
52
+ * @property {"SemantifoldStdlibContract"} schema - Contract schema discriminator.
53
+ * @property {1} schemaVersion - Contract schema version.
54
+ * @property {string} version - Resolved exact version.
55
+ */
56
+ /**
57
+ * @typedef StdlibContractRegistry
58
+ * @property {{identity: string, versions: string[]}[]} modules - Registered modules in stable order.
59
+ * @property {(identity: string, range?: string) => StdlibContract} resolveModule - Versioned module resolution.
60
+ */
61
+
62
+ /**
63
+ * Parses one exact X.Y.Z standard-library version.
64
+ * @param {unknown} value - Candidate version.
65
+ * @returns {VersionTuple | null} Parsed version or null when malformed.
66
+ */
67
+ export function parseStdlibVersion(value) {
68
+ if (typeof value != "string" || !exactVersionPattern.test(value)) return null
69
+ const [major, minor, patch] = value.split(".").map((part) => Number(part))
70
+ return [major, minor, patch]
71
+ }
72
+
73
+ /**
74
+ * Parses one X, X.Y, or X.Y.Z standard-library version range.
75
+ * @param {unknown} value - Candidate range.
76
+ * @returns {VersionRange | null} Half-open range or null when malformed.
77
+ */
78
+ export function parseStdlibVersionRange(value) {
79
+ if (typeof value != "string" || !rangePattern.test(value)) return null
80
+ const parts = value.split(".").map((part) => Number(part))
81
+ const major = parts[0]
82
+ const minor = parts.length > 1 ? parts[1] : 0
83
+ const patch = parts.length > 2 ? parts[2] : 0
84
+
85
+ if (parts.length == 1) return {lower: [major, 0, 0], upper: [major + 1, 0, 0]}
86
+ if (parts.length == 2) return {lower: [major, minor, 0], upper: [major, minor + 1, 0]}
87
+ return {lower: [major, minor, patch], upper: [major, minor, patch + 1]}
88
+ }
89
+
90
+ /**
91
+ * Compares two exact version tuples.
92
+ * @param {VersionTuple} left - Left version.
93
+ * @param {VersionTuple} right - Right version.
94
+ * @returns {number} Negative, zero, or positive ordering.
95
+ */
96
+ export function compareStdlibVersions(left, right) {
97
+ for (let index = 0; index < 3; index += 1) {
98
+ if (left[index] != right[index]) return left[index] < right[index] ? -1 : 1
99
+ }
100
+ return 0
101
+ }
102
+
103
+ /**
104
+ * Derives one protected native provider entry name.
105
+ * @param {string} target - Adopted provider target language.
106
+ * @param {string} module - Legacy operation name or canonical module identity.
107
+ * @param {string} [operation] - Qualified canonical operation name.
108
+ * @returns {string} Protected native entry name.
109
+ */
110
+ export function protectedEntryName(target, module, operation) {
111
+ if (typeof target != "string" || !/^[a-z][a-z0-9-]*$/u.test(target) ||
112
+ typeof module != "string" || (operation !== undefined && (typeof operation != "string" ||
113
+ !declarationNamePattern.test(operation)))) invalidContract("Protected provider entry components are invalid.")
114
+ if (operation === undefined) {
115
+ if (!declarationNamePattern.test(module)) invalidContract("Protected provider operation name is invalid.")
116
+ return `__semantifold_provider_${target}_${module}`
117
+ }
118
+ if (!identityPattern.test(module)) invalidContract("Protected provider module identity is invalid.")
119
+ const encodedModule = [...module].map((character) => character.charCodeAt(0).toString(16).padStart(2, "0")).join("")
120
+
121
+ return `__semantifold_provider_${target}_m${encodedModule.length}_${encodedModule}_${operation}`
122
+ }
123
+
124
+ /**
125
+ * Parses one protected native provider entry name.
126
+ * @param {string} name - Candidate protected entry name.
127
+ * @returns {{target: string, module?: string, operation: string} | null} Parsed binding or null when unparseable.
128
+ */
129
+ export function parseProtectedEntryName(name) {
130
+ const qualified = /^__semantifold_provider_([a-z][a-z0-9-]*)_m([0-9]+)_([0-9a-f]+)_([A-Za-z_][A-Za-z0-9_]*)$/u.exec(name)
131
+
132
+ if (qualified) {
133
+ const encodedLength = Number(qualified[2])
134
+ const encoded = qualified[3]
135
+
136
+ if (!Number.isSafeInteger(encodedLength) || encodedLength != encoded.length || encoded.length % 2 != 0) return null
137
+ let module = ""
138
+
139
+ for (let index = 0; index < encoded.length; index += 2) module += String.fromCharCode(Number.parseInt(encoded.slice(index, index + 2), 16))
140
+ if (!identityPattern.test(module) || protectedEntryName(qualified[1], module, qualified[4]) != name) return null
141
+ return {module, operation: qualified[4], target: qualified[1]}
142
+ }
143
+ const match = /^__semantifold_provider_([a-z][a-z0-9-]*)_(.+)$/u.exec(name)
144
+ if (!match) return null
145
+ return {operation: match[2], target: match[1]}
146
+ }
147
+
148
+ /**
149
+ * Intersects two half-open version ranges.
150
+ * @param {VersionRange} left - Left range.
151
+ * @param {VersionRange} right - Right range.
152
+ * @returns {VersionRange | null} Intersection or null when empty.
153
+ */
154
+ export function intersectStdlibVersionRanges(left, right) {
155
+ const lower = compareStdlibVersions(left.lower, right.lower) >= 0 ? left.lower : right.lower
156
+ const upper = left.upper === null ? right.upper : right.upper === null ? left.upper :
157
+ compareStdlibVersions(left.upper, right.upper) <= 0 ? left.upper : right.upper
158
+
159
+ if (upper !== null && compareStdlibVersions(lower, upper) >= 0) return null
160
+ return {lower, upper}
161
+ }
162
+
163
+ /**
164
+ * Checks whether one exact version satisfies one half-open range.
165
+ * @param {VersionTuple} version - Candidate version.
166
+ * @param {VersionRange} range - Declared range.
167
+ * @returns {boolean} Whether the version satisfies the range.
168
+ */
169
+ export function stdlibVersionSatisfies(version, range) {
170
+ if (compareStdlibVersions(version, range.lower) < 0) return false
171
+ return range.upper === null || compareStdlibVersions(version, range.upper) < 0
172
+ }
173
+
174
+ /**
175
+ * Creates the built-in versioned canonical stdlib contract registry.
176
+ * @param {unknown} records - Optional override record set; built-in probe contract by default.
177
+ * @returns {Readonly<StdlibContractRegistry>} Frozen registry.
178
+ */
179
+ export function createStdlibContractRegistry(records = builtinContracts()) {
180
+ if (!isDenseArray(records)) invalidContract("Canonical contract records must be an ordered dense array.")
181
+
182
+ /** @type {Map<string, Map<string, StdlibContractModule>>} */
183
+ const modules = new Map()
184
+
185
+ for (const candidate of records) {
186
+ const record = validateContractRecord(candidate)
187
+ const versions = modules.get(record.identity) ?? new Map()
188
+
189
+ if (versions.has(record.version)) invalidContract(`Duplicate canonical contract '${record.identity}' version '${record.version}'.`)
190
+ versions.set(record.version, record)
191
+ modules.set(record.identity, versions)
192
+ }
193
+ for (const record of modules.values()) {
194
+ for (const module of record.values()) validateContractDependencies(module, modules)
195
+ }
196
+ const frozenModules = [...modules.entries()]
197
+ .map(([identity, versions]) => ({
198
+ identity,
199
+ versions: [...versions.keys()].map((version) => /** @type {VersionTuple} */ (parseStdlibVersion(version)))
200
+ .sort(compareStdlibVersions)
201
+ .map(([major, minor, patch]) => `${major}.${minor}.${patch}`)
202
+ }))
203
+ .map(deepFreeze)
204
+ const store = deepFreeze(/** @type {{modules: [string, Readonly<Map<string, Readonly<StdlibContractModule>>>][]}} */ ({
205
+ modules: [...modules.entries()].map(([identity, versions]) => [identity, deepFreeze(versions)])
206
+ }))
207
+ return Object.freeze(/** @type {StdlibContractRegistry} */ ({
208
+ modules: Object.freeze(frozenModules),
209
+ resolveModule(identity, range) {
210
+ return resolveRegistryModule(store, identity, range)
211
+ }
212
+ }))
213
+ }
214
+
215
+ /**
216
+ * Resolves one module identity plus optional range against one registry store.
217
+ * @param {{modules: [string, Readonly<Map<string, Readonly<StdlibContractModule>>>][]}} store - Registry store.
218
+ * @param {string} identity - Canonical module identity.
219
+ * @param {string | undefined} [range] - Declared version range.
220
+ * @returns {StdlibContract} Detached frozen contract.
221
+ */
222
+ function resolveRegistryModule(store, identity, range) {
223
+ const versions = store.modules.find(([candidate]) => candidate == identity)?.[1]
224
+
225
+ if (!versions) unknownModule(identity)
226
+ const parsed = range === undefined ? /** @type {VersionRange} */ ({lower: [0, 0, 0], upper: null}) : parseStdlibVersionRange(range)
227
+
228
+ if (!parsed) malformedRange()
229
+ /** @type {VersionTuple | undefined} */
230
+ let resolved
231
+
232
+ for (const version of versions.keys()) {
233
+ const tuple = /** @type {VersionTuple} */ (parseStdlibVersion(version))
234
+
235
+ if (stdlibVersionSatisfies(tuple, parsed) && (resolved === undefined || compareStdlibVersions(tuple, resolved) > 0)) {
236
+ resolved = tuple
237
+ }
238
+ }
239
+ if (resolved === undefined) incompatibleVersion(identity)
240
+ const record = /** @type {Readonly<StdlibContractModule>} */ (versions.get(`${resolved[0]}.${resolved[1]}.${resolved[2]}`))
241
+
242
+ return deepFreeze({
243
+ dependencies: record.dependencies,
244
+ failures: record.failures,
245
+ identity: record.identity,
246
+ operations: record.operations,
247
+ resources: record.resources,
248
+ schema: /** @type {const} */ ("SemantifoldStdlibContract"),
249
+ schemaVersion: /** @type {const} */ (1),
250
+ version: `${resolved[0]}.${resolved[1]}.${resolved[2]}`
251
+ })
252
+ }
253
+
254
+ /**
255
+ * Lists the built-in canonical stdlib modules with their registered versions.
256
+ * @returns {Readonly<{identity: string, versions: string[]}[]>} Frozen module list.
257
+ */
258
+ export function listStdlibModules() {
259
+ return builtinRegistry.modules
260
+ }
261
+
262
+ /**
263
+ * Resolves one built-in canonical stdlib module by identity and optional range.
264
+ * @param {string} identity - Canonical module identity.
265
+ * @param {string} [range] - Declared version range.
266
+ * @returns {StdlibContract} Detached frozen contract.
267
+ */
268
+ export function resolveStdlibModule(identity, range) {
269
+ return builtinRegistry.resolveModule(identity, range)
270
+ }
271
+
272
+ /**
273
+ * Declares the built-in Task 034 resource-probe canonical contract.
274
+ * @returns {unknown} Unvalidated built-in record.
275
+ */
276
+ function builtinProbeContract() {
277
+ return {
278
+ dependencies: [],
279
+ failures: [
280
+ {name: "ProbeOperationFailure"},
281
+ {name: "ProbeAcquireFailure"},
282
+ {name: "ProbeReadFailure"},
283
+ {name: "ProbeCloseFailure"},
284
+ {name: "ProbeResourceClosed"}
285
+ ],
286
+ identity: "semantifold.task034.resource-probe",
287
+ operations: [
288
+ {
289
+ dependencies: [],
290
+ effects: ["host"],
291
+ evaluationOrder: "left-to-right",
292
+ failures: ["ProbeOperationFailure"],
293
+ name: "probeEffect",
294
+ parameters: [{name: "label", type: "string"}, {name: "value", type: "integer"}, {name: "fail", type: "boolean"}],
295
+ resourceFlow: {kind: "none"},
296
+ returnType: "integer",
297
+ semantics: canonicalSemantics()
298
+ },
299
+ {
300
+ dependencies: [],
301
+ effects: ["host"],
302
+ evaluationOrder: "left-to-right",
303
+ failures: ["ProbeAcquireFailure"],
304
+ name: "probeAcquire",
305
+ parameters: [{name: "fail", type: "boolean"}],
306
+ resourceFlow: {kind: "acquire", resource: "ProbeResource"},
307
+ returnType: "ProbeResource",
308
+ semantics: canonicalSemantics({ownership: "acquired"})
309
+ },
310
+ {
311
+ dependencies: [],
312
+ effects: ["host"],
313
+ evaluationOrder: "left-to-right",
314
+ failures: ["ProbeReadFailure", "ProbeResourceClosed"],
315
+ name: "probeRead",
316
+ parameters: [{name: "resource", type: "ProbeResource"}, {name: "fail", type: "boolean"}],
317
+ resourceFlow: {kind: "borrow", parameterIndex: 0, terminalFailure: "ProbeResourceClosed"},
318
+ returnType: "optional:string",
319
+ semantics: canonicalSemantics({
320
+ close: "use-after-close-fails",
321
+ eof: "absent-value",
322
+ encoding: "utf-8",
323
+ newline: "strip-line-terminator",
324
+ ownership: "borrowed"
325
+ })
326
+ },
327
+ {
328
+ dependencies: [],
329
+ effects: ["host"],
330
+ evaluationOrder: "left-to-right",
331
+ failures: ["ProbeCloseFailure", "ProbeResourceClosed"],
332
+ name: "probeClose",
333
+ parameters: [{name: "resource", type: "ProbeResource"}, {name: "fail", type: "boolean"}],
334
+ resourceFlow: {kind: "close", parameterIndex: 0, terminalFailure: "ProbeResourceClosed"},
335
+ returnType: "void",
336
+ semantics: canonicalSemantics({close: "repeated-close-fails", ownership: "consumed"})
337
+ },
338
+ {
339
+ dependencies: [],
340
+ effects: ["host"],
341
+ evaluationOrder: "left-to-right",
342
+ failures: [],
343
+ name: "probeTrace",
344
+ parameters: [],
345
+ resourceFlow: {kind: "none"},
346
+ returnType: "string",
347
+ semantics: canonicalSemantics()
348
+ }
349
+ ],
350
+ resources: [{name: "ProbeResource"}],
351
+ version: "1.0.0"
352
+ }
353
+ }
354
+
355
+ /**
356
+ * Declares the complete built-in canonical registry input.
357
+ * @returns {unknown[]} Unvalidated built-in records.
358
+ */
359
+ function builtinContracts() {
360
+ return [builtinProbeContract(), builtinSocketClientContract(), builtinTextStreamContract(),
361
+ builtinOutputContract(), builtinResourceContract()]
362
+ }
363
+
364
+ /**
365
+ * Declares the built-in SocketClient v1 contract.
366
+ * @returns {unknown} Unvalidated SocketClient v1 record.
367
+ */
368
+ function builtinSocketClientContract() {
369
+ const byteStream = {module: "semantifold.resource", name: "ByteStream"}
370
+
371
+ return {
372
+ dependencies: [{module: "semantifold.resource", range: "1"}],
373
+ failures: [{name: "InvalidHost"}, {name: "InvalidPort"}, {name: "ConnectionFailure"}],
374
+ identity: "semantifold.socket-client",
375
+ operations: [{
376
+ dependencies: [], effects: ["host"], evaluationOrder: "left-to-right",
377
+ failures: ["InvalidHost", "InvalidPort", "ConnectionFailure"], name: "v1_connect",
378
+ parameters: [{name: "host", type: "string"}, {name: "port", type: "integer"}],
379
+ resourceFlow: {kind: "acquire", resource: byteStream}, returnType: byteStream,
380
+ semantics: canonicalSemantics({ownership: "acquired"})
381
+ }],
382
+ resources: [],
383
+ version: "1.0.0"
384
+ }
385
+ }
386
+
387
+ /**
388
+ * Declares the built-in TextStream v1 contract.
389
+ * @returns {unknown} Unvalidated TextStream v1 record.
390
+ */
391
+ function builtinTextStreamContract() {
392
+ const byteStream = {module: "semantifold.resource", name: "ByteStream"}
393
+ const resourceClosed = {module: "semantifold.resource", name: "ResourceClosed"}
394
+
395
+ return {
396
+ dependencies: [{module: "semantifold.resource", range: "1"}],
397
+ failures: [{name: "ReadFailure"}, {name: "DecodeFailure"}],
398
+ identity: "semantifold.text-stream",
399
+ operations: [{
400
+ dependencies: [], effects: ["host"], evaluationOrder: "left-to-right",
401
+ failures: ["ReadFailure", "DecodeFailure", resourceClosed], name: "v1_read_line",
402
+ parameters: [{name: "resource", type: byteStream}],
403
+ resourceFlow: {kind: "borrow", parameterIndex: 0, terminalFailure: resourceClosed},
404
+ returnType: "optional:string",
405
+ semantics: canonicalSemantics({close: "use-after-close-fails", eof: "absent-value", encoding: "utf-8",
406
+ newline: "retain-line-terminator", ownership: "borrowed"})
407
+ }],
408
+ resources: [],
409
+ version: "1.0.0"
410
+ }
411
+ }
412
+
413
+ /**
414
+ * Declares the built-in Output v1 contract.
415
+ * @returns {unknown} Unvalidated Output v1 record.
416
+ */
417
+ function builtinOutputContract() {
418
+ return {
419
+ dependencies: [], failures: [{name: "WriteFailure"}], identity: "semantifold.output",
420
+ operations: [{
421
+ dependencies: [], effects: ["host"], evaluationOrder: "left-to-right", failures: ["WriteFailure"],
422
+ name: "v1_write_line", parameters: [{name: "text", type: "string"}], resourceFlow: {kind: "none"},
423
+ returnType: "void", semantics: canonicalSemantics({encoding: "utf-8", newline: "append-lf-if-missing"})
424
+ }],
425
+ resources: [], version: "1.0.0"
426
+ }
427
+ }
428
+
429
+ /**
430
+ * Declares the built-in Resource v1 contract.
431
+ * @returns {unknown} Unvalidated Resource v1 record.
432
+ */
433
+ function builtinResourceContract() {
434
+ return {
435
+ dependencies: [], failures: [{name: "CloseFailure"}, {name: "ResourceClosed"}], identity: "semantifold.resource",
436
+ operations: [{
437
+ dependencies: [], effects: ["host"], evaluationOrder: "left-to-right",
438
+ failures: ["CloseFailure", "ResourceClosed"], name: "v1_close",
439
+ parameters: [{name: "resource", type: "ByteStream"}],
440
+ resourceFlow: {kind: "close", parameterIndex: 0, terminalFailure: "ResourceClosed"}, returnType: "void",
441
+ semantics: canonicalSemantics({close: "repeated-close-fails", ownership: "consumed"})
442
+ }],
443
+ resources: [{name: "ByteStream"}], version: "1.0.0"
444
+ }
445
+ }
446
+
447
+ /**
448
+ * Builds one closed semantics declaration with canonical defaults.
449
+ * @param {Partial<Record<keyof typeof semanticsValues, string>>} [overrides] - Non-default closed values.
450
+ * @returns {Record<string, string>} Closed semantics fields.
451
+ */
452
+ function canonicalSemantics(overrides = {}) {
453
+ return {
454
+ blocking: "synchronous",
455
+ close: "not-applicable",
456
+ eof: "not-applicable",
457
+ encoding: "not-applicable",
458
+ newline: "not-applicable",
459
+ ownership: "not-applicable",
460
+ timeout: "none",
461
+ ...overrides
462
+ }
463
+ }
464
+
465
+ /**
466
+ * Validates one canonical contract record and returns a detached clone.
467
+ * @param {unknown} candidate - Candidate record.
468
+ * @returns {StdlibContractModule} Detached record.
469
+ */
470
+ function validateContractRecord(candidate) {
471
+ if (!isPlainObject(candidate)) invalidContract("Every canonical contract record must be a plain object.")
472
+ requireKeys(candidate, ["dependencies", "failures", "identity", "operations", "resources", "version"], "contract record")
473
+ const identity = /** @type {string} */ (candidate.identity)
474
+
475
+ if (typeof identity != "string" || !identityPattern.test(identity)) invalidContract("Canonical contract identity is invalid.")
476
+ const version = /** @type {string} */ (candidate.version)
477
+
478
+ if (parseStdlibVersion(version) === null) invalidContract(`Canonical contract version '${String(version)}' is invalid.`)
479
+ const resources = validateNamedList(candidate.resources, "resource")
480
+ const failures = validateNamedList(candidate.failures, "failure")
481
+ const resourceNames = new Set(resources.map(({name}) => name))
482
+ const failureNames = new Set(failures.map(({name}) => name))
483
+ const operationNames = new Set()
484
+ const dependencies = validateModuleDependencies(candidate.dependencies, identity)
485
+
486
+ if (!isDenseArray(candidate.operations)) invalidContract("Canonical contract operations must be a dense array.")
487
+ const operations = /** @type {unknown[]} */ (candidate.operations).map((operation) =>
488
+ validateContractOperation(operation, resourceNames, failureNames, operationNames))
489
+
490
+ return deepFreeze({
491
+ dependencies,
492
+ failures,
493
+ identity,
494
+ operations,
495
+ resources,
496
+ version: /** @type {string} */ (version)
497
+ })
498
+ }
499
+
500
+ /**
501
+ * Validates one canonical contract operation.
502
+ * @param {unknown} candidate - Candidate operation.
503
+ * @param {Set<string>} resourceNames - Declared resource names.
504
+ * @param {Set<string>} failureNames - Declared failure names.
505
+ * @param {Set<string>} operationNames - Already-declared operation names.
506
+ * @returns {StdlibContractOperation} Detached operation.
507
+ */
508
+ function validateContractOperation(candidate, resourceNames, failureNames, operationNames) {
509
+ if (!isPlainObject(candidate)) invalidContract("Every canonical contract operation must be a plain object.")
510
+ requireKeys(candidate, ["dependencies", "effects", "evaluationOrder", "failures", "name", "parameters", "resourceFlow", "returnType", "semantics"], "contract operation")
511
+ const name = /** @type {string} */ (candidate.name)
512
+
513
+ if (typeof name != "string" || !declarationNamePattern.test(name) || operationNames.has(name)) {
514
+ invalidContract("Canonical contract operation name is invalid or duplicate.")
515
+ }
516
+ operationNames.add(name)
517
+ if (!isDenseArray(candidate.effects) || candidate.effects.length != 1 || candidate.effects[0] != "host") {
518
+ invalidContract(`Operation '${name}' requires the single host effect declaration.`)
519
+ }
520
+ if (candidate.evaluationOrder != "left-to-right") invalidContract(`Operation '${name}' requires left-to-right evaluation.`)
521
+ if (!isDenseArray(candidate.failures)) {
522
+ invalidContract(`Operation '${name}' declares unknown or duplicate failures.`)
523
+ }
524
+ const failures = candidate.failures.map((failure) => normalizeDeclarationReference(failure, failureNames, `Operation '${name}' failure`))
525
+ if (new Set(failures.map(referenceKey)).size != failures.length) invalidContract(`Operation '${name}' repeats a declared failure.`)
526
+ const parameterNames = new Set()
527
+ /** @type {{name: string, type: string | CanonicalDeclarationReference}[]} */
528
+ const parameters = []
529
+
530
+ if (!isDenseArray(candidate.parameters)) invalidContract(`Operation '${name}' parameters must be a dense array.`)
531
+ for (const parameter of /** @type {unknown[]} */ (candidate.parameters)) {
532
+ if (!isPlainObject(parameter)) invalidContract(`Operation '${name}' parameters must be plain objects.`)
533
+ requireKeys(parameter, ["name", "type"], `operation '${name}' parameter`)
534
+ const parameterName = /** @type {string} */ (parameter.name)
535
+
536
+ if (typeof parameterName != "string" || !declarationNamePattern.test(parameterName) || parameterNames.has(parameterName)) {
537
+ invalidContract(`Operation '${name}' parameter name is invalid or duplicate.`)
538
+ }
539
+ parameterNames.add(parameterName)
540
+ const parameterType = normalizeCanonicalValueType(parameter.type, resourceNames, `operation '${name}' parameter '${parameterName}'`)
541
+
542
+ if (parameterType === null) {
543
+ invalidContract(`Operation '${name}' parameter '${parameterName}' type is outside the closed canonical value set.`)
544
+ }
545
+ parameters.push({name: parameterName, type: parameterType})
546
+ }
547
+ const returnType = candidate.returnType == "void" ? "void" : normalizeCanonicalValueType(candidate.returnType, resourceNames, `operation '${name}' return type`)
548
+
549
+ if (returnType === null) {
550
+ invalidContract(`Operation '${name}' return type is outside the closed canonical value set.`)
551
+ }
552
+ const resourceFlow = validateContractResourceFlow(candidate.resourceFlow, parameters, failures, name)
553
+ const dependencies = validateOperationDependencies(candidate.dependencies)
554
+ const semantics = validateContractSemantics(candidate.semantics, name)
555
+
556
+ return deepFreeze({
557
+ dependencies,
558
+ effects: /** @type {const} */ (["host"]),
559
+ evaluationOrder: /** @type {const} */ ("left-to-right"),
560
+ failures,
561
+ name,
562
+ parameters,
563
+ resourceFlow,
564
+ returnType,
565
+ semantics
566
+ })
567
+ }
568
+
569
+ /**
570
+ * Validates one closed canonical value type spelling.
571
+ * @param {unknown} candidate - Candidate type.
572
+ * @param {Set<string>} resourceNames - Declared resource names.
573
+ * @param {string} _subject - Diagnostic subject reserved for caller context.
574
+ * @returns {string | CanonicalDeclarationReference | null} Detached type or null.
575
+ */
576
+ function normalizeCanonicalValueType(candidate, resourceNames, _subject) {
577
+ if (typeof candidate == "string") {
578
+ if (scalarNames.has(candidate) || resourceNames.has(candidate)) return candidate
579
+ const optional = /^optional:([a-z]+)$/u.exec(candidate)
580
+
581
+ return optional && scalarNames.has(optional[1]) ? candidate : null
582
+ }
583
+ if (isPlainObject(candidate) && Object.keys(candidate).sort().join(",") == "module,name" &&
584
+ typeof candidate.module == "string" && identityPattern.test(candidate.module) && typeof candidate.name == "string" &&
585
+ declarationNamePattern.test(candidate.name)) return {module: candidate.module, name: candidate.name}
586
+ return null
587
+ }
588
+
589
+ /**
590
+ * Validates one closed resource transition against its parameters and failures.
591
+ * @param {unknown} candidate - Candidate transition.
592
+ * @param {{name: string, type: string | CanonicalDeclarationReference}[]} parameters - Validated parameters.
593
+ * @param {(string | CanonicalDeclarationReference)[]} failures - Validated failure names.
594
+ * @param {string} operation - Operation name.
595
+ * @returns {object} Detached transition.
596
+ */
597
+ function validateContractResourceFlow(candidate, parameters, failures, operation) {
598
+ if (!isPlainObject(candidate)) invalidContract(`Operation '${operation}' requires a resource flow declaration.`)
599
+ const ownedParameters = parameters.flatMap((parameter, index) => isOwnedCanonicalType(parameter.type) ? [index] : [])
600
+
601
+ if (Object.keys(candidate).sort().join(",") == "kind" && candidate.kind == "none") {
602
+ if (ownedParameters.length > 0) invalidContract(`Operation '${operation}' owns a parameter without a transition.`)
603
+ return deepFreeze({kind: /** @type {const} */ ("none")})
604
+ }
605
+ if (Object.keys(candidate).sort().join(",") == "kind,resource" && candidate.kind == "acquire") {
606
+ const resource = typeof candidate.resource == "string" && declarationNamePattern.test(candidate.resource)
607
+ ? candidate.resource
608
+ : normalizeCanonicalValueType(candidate.resource, new Set(), `operation '${operation}' acquisition`)
609
+ if (resource === null || ownedParameters.length > 0) {
610
+ invalidContract(`Operation '${operation}' acquisition flow is incomplete.`)
611
+ }
612
+ return deepFreeze({kind: /** @type {const} */ ("acquire"), resource})
613
+ }
614
+ if (["borrow", "close"].includes(String(candidate.kind)) &&
615
+ Object.keys(candidate).sort().join(",") == "kind,parameterIndex,terminalFailure") {
616
+ const parameterIndex = /** @type {number} */ (candidate.parameterIndex)
617
+
618
+ if (!Number.isSafeInteger(parameterIndex) || parameterIndex < 0 || parameterIndex >= parameters.length ||
619
+ ownedParameters.length != 1 || ownedParameters[0] != parameterIndex ||
620
+ !failures.some((failure) => referenceKey(failure) == referenceKey(candidate.terminalFailure))) {
621
+ invalidContract(`Operation '${operation}' ${String(candidate.kind)} flow is incomplete.`)
622
+ }
623
+ return deepFreeze({kind: /** @type {"borrow" | "close"} */ (candidate.kind), parameterIndex,
624
+ terminalFailure: normalizeFailureFlowReference(candidate.terminalFailure)})
625
+ }
626
+ return invalidContract(`Operation '${operation}' declares an unknown resource flow.`)
627
+ }
628
+
629
+ /**
630
+ * Validates one canonical operation dependency list.
631
+ * @param {unknown} candidate - Candidate dependencies.
632
+ * @returns {{module: string, operation: string, range: VersionRange}[]} Detached dependencies.
633
+ */
634
+ function validateOperationDependencies(candidate) {
635
+ if (!isDenseArray(candidate)) invalidContract("Canonical contract dependencies must be a dense array.")
636
+ /** @type {{module: string, operation: string, range: VersionRange}[]} */
637
+ const dependencies = []
638
+
639
+ for (const dependency of candidate) {
640
+ if (!isPlainObject(dependency)) invalidContract("Every canonical contract dependency must be a plain object.")
641
+ requireKeys(dependency, ["module", "operation", "range"], "contract dependency")
642
+ const module = /** @type {string} */ (dependency.module)
643
+ const operation = /** @type {string} */ (dependency.operation)
644
+ const range = parseStdlibVersionRange(dependency.range)
645
+
646
+ if (typeof module != "string" || !identityPattern.test(module) ||
647
+ typeof operation != "string" || !declarationNamePattern.test(operation) || range === null) {
648
+ invalidContract("Canonical contract dependency module, operation, or range is invalid.")
649
+ }
650
+ dependencies.push({module, operation, range})
651
+ }
652
+ return dependencies
653
+ }
654
+
655
+ /**
656
+ * Validates canonical operation dependencies against the complete registry identity set.
657
+ * @param {StdlibContractModule} record - Validated record.
658
+ * @param {Map<string, Map<string, StdlibContractModule>>} modules - All registered module versions.
659
+ * @returns {void}
660
+ */
661
+ function validateContractDependencies(record, modules) {
662
+ const allowedDependencies = new Map(record.dependencies.map((dependency) => [dependency.module, dependency.range]))
663
+
664
+ for (const dependency of record.dependencies) {
665
+ const versions = modules.get(dependency.module)
666
+
667
+ if (!versions || ![...versions.keys()].some((version) => stdlibVersionSatisfies(/** @type {VersionTuple} */ (parseStdlibVersion(version)), dependency.range))) {
668
+ invalidContract(`Canonical module '${record.identity}' depends on missing or incompatible module '${dependency.module}'.`)
669
+ }
670
+ }
671
+ for (const operation of record.operations) {
672
+ for (const reference of operation.parameters.map(({type}) => type).concat([operation.returnType]).filter(isDeclarationReference)) {
673
+ validateForeignDeclarationReference(record, reference, "resource", allowedDependencies, modules)
674
+ }
675
+ for (const reference of operation.failures.filter(isDeclarationReference)) {
676
+ validateForeignDeclarationReference(record, reference, "failure", allowedDependencies, modules)
677
+ }
678
+ for (const dependency of operation.dependencies) {
679
+ if (!modules.has(dependency.module)) {
680
+ invalidContract(`Operation '${operation.name}' depends on unknown canonical module '${dependency.module}'.`)
681
+ }
682
+ if (dependency.module == record.identity && dependency.operation == operation.name) {
683
+ invalidContract(`Operation '${operation.name}' declares a self-cycle dependency.`)
684
+ }
685
+ }
686
+ }
687
+ }
688
+
689
+ /**
690
+ * Validates declaration-only module dependencies.
691
+ * @param {unknown} candidate - Candidate dependency list.
692
+ * @param {string} identity - Owning module identity.
693
+ * @returns {{module: string, range: VersionRange}[]} Detached dependencies.
694
+ */
695
+ function validateModuleDependencies(candidate, identity) {
696
+ if (!isDenseArray(candidate)) invalidContract("Canonical module dependencies must be a dense array.")
697
+ const names = new Set()
698
+
699
+ return candidate.map((dependency) => {
700
+ if (!isPlainObject(dependency)) invalidContract("Every canonical module dependency must be a plain object.")
701
+ requireKeys(dependency, ["module", "range"], "module dependency")
702
+ const module = /** @type {string} */ (dependency.module)
703
+ const range = parseStdlibVersionRange(dependency.range)
704
+
705
+ if (typeof module != "string" || !identityPattern.test(module) || module == identity || names.has(module) || range === null) {
706
+ invalidContract("Canonical module dependency is invalid, duplicate, self-referential, or malformed.")
707
+ }
708
+ names.add(module)
709
+ return {module, range}
710
+ })
711
+ }
712
+
713
+ /**
714
+ * Validates one dependency-qualified resource or failure reference.
715
+ * @param {StdlibContractModule} record - Owning module.
716
+ * @param {CanonicalDeclarationReference} reference - Qualified declaration.
717
+ * @param {"resource" | "failure"} kind - Declaration kind.
718
+ * @param {Map<string, VersionRange>} allowedDependencies - Direct dependency ranges.
719
+ * @param {Map<string, Map<string, StdlibContractModule>>} modules - Registry modules.
720
+ * @returns {void}
721
+ */
722
+ function validateForeignDeclarationReference(record, reference, kind, allowedDependencies, modules) {
723
+ const range = allowedDependencies.get(reference.module)
724
+
725
+ if (!range) invalidContract(`Canonical module '${record.identity}' uses undeclared dependency '${reference.module}'.`)
726
+ const versions = /** @type {Map<string, StdlibContractModule>} */ (modules.get(reference.module))
727
+ const matches = [...versions.values()].filter((module) =>
728
+ stdlibVersionSatisfies(/** @type {VersionTuple} */ (parseStdlibVersion(module.version)), range))
729
+ const declarations = kind == "resource" ? matches.flatMap(({resources}) => resources) : matches.flatMap(({failures}) => failures)
730
+
731
+ if (!declarations.some(({name}) => name == reference.name)) {
732
+ invalidContract(`Canonical ${kind} '${reference.module}.${reference.name}' is not declared by a compatible dependency.`)
733
+ }
734
+ }
735
+
736
+ /**
737
+ * Normalizes one local or dependency-qualified declaration reference.
738
+ * @param {unknown} candidate - Candidate reference.
739
+ * @param {Set<string>} localNames - Declared local names.
740
+ * @param {string} subject - Diagnostic subject.
741
+ * @returns {string | CanonicalDeclarationReference} Detached reference.
742
+ */
743
+ function normalizeDeclarationReference(candidate, localNames, subject) {
744
+ if (typeof candidate == "string" && localNames.has(candidate)) return candidate
745
+ if (isDeclarationReference(candidate)) return {module: candidate.module, name: candidate.name}
746
+ return invalidContract(`${subject} is not a declared local or qualified canonical declaration.`)
747
+ }
748
+
749
+ /**
750
+ * Normalizes a terminal failure reference after membership validation.
751
+ * @param {unknown} candidate - Candidate failure reference.
752
+ * @returns {string | CanonicalDeclarationReference} Detached reference.
753
+ */
754
+ function normalizeFailureFlowReference(candidate) {
755
+ if (typeof candidate == "string") return candidate
756
+ if (isDeclarationReference(candidate)) return {module: candidate.module, name: candidate.name}
757
+ return invalidContract("Resource flow terminal failure is invalid.")
758
+ }
759
+
760
+ /**
761
+ * Checks one canonical qualified declaration reference.
762
+ * @param {unknown} candidate - Candidate reference.
763
+ * @returns {candidate is CanonicalDeclarationReference} Whether the reference is exact.
764
+ */
765
+ function isDeclarationReference(candidate) {
766
+ return isPlainObject(candidate) && Object.keys(candidate).sort().join(",") == "module,name" &&
767
+ typeof candidate.module == "string" && identityPattern.test(candidate.module) &&
768
+ typeof candidate.name == "string" && declarationNamePattern.test(candidate.name)
769
+ }
770
+
771
+ /**
772
+ * Encodes one declaration reference for equality checks.
773
+ * @param {unknown} candidate - Local or qualified reference.
774
+ * @returns {string} Stable equality key.
775
+ */
776
+ function referenceKey(candidate) {
777
+ return typeof candidate == "string" ? `local:${candidate}` : isDeclarationReference(candidate)
778
+ ? `${candidate.module}:${candidate.name}` : `invalid:${String(candidate)}`
779
+ }
780
+
781
+ /**
782
+ * Reports whether a canonical type denotes an owned resource.
783
+ * @param {string | CanonicalDeclarationReference} candidate - Canonical type.
784
+ * @returns {boolean} Whether the type is owned.
785
+ */
786
+ function isOwnedCanonicalType(candidate) {
787
+ return isDeclarationReference(candidate) || (typeof candidate == "string" && !scalarNames.has(candidate) &&
788
+ !candidate.startsWith("optional:") && candidate != "void")
789
+ }
790
+
791
+ /**
792
+ * Validates one closed semantics declaration.
793
+ * @param {unknown} candidate - Candidate semantics.
794
+ * @param {string} operation - Operation name.
795
+ * @returns {Record<string, string>} Closed semantics fields.
796
+ */
797
+ function validateContractSemantics(candidate, operation) {
798
+ if (!isPlainObject(candidate) || Object.keys(candidate).sort().join(",") !=
799
+ "blocking,close,encoding,eof,newline,ownership,timeout") {
800
+ invalidContract(`Operation '${operation}' requires the closed canonical semantics fields.`)
801
+ }
802
+ /** @type {Record<string, string>} */
803
+ const semantics = {}
804
+
805
+ for (const [field, allowed] of Object.entries(semanticsValues)) {
806
+ const value = /** @type {string} */ (candidate[field])
807
+
808
+ if (typeof value != "string" || !allowed.has(value)) {
809
+ invalidContract(`Operation '${operation}' declares a non-canonical '${field}' semantics value.`)
810
+ }
811
+ semantics[field] = value
812
+ }
813
+ return deepFreeze(semantics)
814
+ }
815
+
816
+ /**
817
+ * Validates one dense ordered single-field named declaration list.
818
+ * @param {unknown} candidate - Candidate list.
819
+ * @param {string} subject - Diagnostic subject.
820
+ * @returns {{name: string}[]} Detached declarations.
821
+ */
822
+ function validateNamedList(candidate, subject) {
823
+ if (!isDenseArray(candidate)) invalidContract(`Canonical contract ${subject}s must be a dense array.`)
824
+ const names = new Set()
825
+ /** @type {{name: string}[]} */
826
+ const declarations = []
827
+
828
+ for (const declaration of candidate) {
829
+ if (!isPlainObject(declaration) || Object.keys(declaration).join(",") != "name" ||
830
+ typeof declaration.name != "string" || !declarationNamePattern.test(declaration.name) || names.has(declaration.name)) {
831
+ invalidContract(`Canonical contract ${subject} declarations must be uniquely named.`)
832
+ }
833
+ names.add(/** @type {string} */ (declaration.name))
834
+ declarations.push({name: /** @type {string} */ (declaration.name)})
835
+ }
836
+ return declarations
837
+ }
838
+
839
+ /**
840
+ * Reports an unknown canonical module identity.
841
+ * @param {string} identity - Unknown identity.
842
+ * @returns {never} Always throws.
843
+ */
844
+ function unknownModule(identity) {
845
+ throw new SemantifoldDiagnostic({code: "STDLIB_MODULE_UNKNOWN", language: "stdlib",
846
+ message: `Standard-library module '${identity}' is not a registered canonical contract.`})
847
+ }
848
+
849
+ /**
850
+ * Reports one malformed version range.
851
+ * @returns {never} Always throws.
852
+ */
853
+ function malformedRange() {
854
+ throw new SemantifoldDiagnostic({code: "STDLIB_VERSION_MALFORMED", language: "stdlib",
855
+ message: "Standard-library version ranges use X, X.Y, or X.Y.Z without leading zeros or prerelease labels."})
856
+ }
857
+
858
+ /**
859
+ * Reports one unsatisfiable version range.
860
+ * @param {string} identity - Constrained module identity.
861
+ * @returns {never} Always throws.
862
+ */
863
+ function incompatibleVersion(identity) {
864
+ throw new SemantifoldDiagnostic({code: "STDLIB_VERSION_INCOMPATIBLE", language: "stdlib",
865
+ message: `No registered version of '${identity}' satisfies the declared standard-library version range.`})
866
+ }
867
+
868
+ /**
869
+ * Raises one stable canonical contract diagnostic.
870
+ * @param {string} message - Diagnostic message.
871
+ * @returns {never} Always throws.
872
+ */
873
+ function invalidContract(message) {
874
+ throw new SemantifoldDiagnostic({code: "STDLIB_CONTRACT_INVALID", language: "stdlib", message})
875
+ }
876
+
877
+ /**
878
+ * Requires one exact field set.
879
+ * @param {Record<string, unknown>} value - Candidate object.
880
+ * @param {string[]} keys - Required keys.
881
+ * @param {string} subject - Diagnostic subject.
882
+ * @returns {void}
883
+ */
884
+ function requireKeys(value, keys, subject) {
885
+ if (Object.keys(value).sort().join(",") != [...keys].sort().join(",")) invalidContract(`Invalid ${subject} fields.`)
886
+ }
887
+
888
+ /**
889
+ * Checks an ordered dense array.
890
+ * @param {unknown} value - Candidate array.
891
+ * @returns {value is unknown[]} Whether the value is dense.
892
+ */
893
+ function isDenseArray(value) {
894
+ return Array.isArray(value) && value.every((_item, index) => Object.hasOwn(value, index))
895
+ }
896
+
897
+ /**
898
+ * Checks for an ordinary string-keyed object.
899
+ * @param {unknown} value - Candidate value.
900
+ * @returns {value is Record<string, unknown>} Whether the value is a plain object.
901
+ */
902
+ function isPlainObject(value) {
903
+ return value !== null && typeof value == "object" && !Array.isArray(value) &&
904
+ Object.getPrototypeOf(value) == Object.prototype
905
+ }
906
+
907
+ /**
908
+ * Recursively freezes a detached value.
909
+ * @template {object} Value
910
+ * @param {Value} value - Object to freeze.
911
+ * @returns {Readonly<Value>} Frozen object.
912
+ */
913
+ function deepFreeze(value) {
914
+ for (const child of Object.values(value)) {
915
+ if (child && typeof child == "object" && !Object.isFrozen(child)) deepFreeze(child)
916
+ }
917
+ return Object.freeze(value)
918
+ }
919
+
920
+ /** @type {Readonly<StdlibContractRegistry>} */
921
+ const builtinRegistry = createStdlibContractRegistry()