functionalscript 0.44.0 → 0.46.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 (571) hide show
  1. package/README.md +5 -3
  2. package/fjs/asn.1/module.f.mjs +8 -1
  3. package/fjs/asn.1/proof.f.d.mts +15 -0
  4. package/fjs/asn.1/proof.f.mjs +31 -3
  5. package/fjs/asserts/module.f.d.mts +14 -0
  6. package/fjs/asserts/module.f.mjs +20 -0
  7. package/fjs/asserts/proof.f.d.mts +3 -0
  8. package/fjs/asserts/proof.f.mjs +15 -1
  9. package/fjs/basen/base128/module.f.mjs +22 -5
  10. package/fjs/basen/base128/proof.f.d.mts +3 -1
  11. package/fjs/basen/base128/proof.f.mjs +3 -1
  12. package/fjs/basen/base64/module.f.mjs +7 -3
  13. package/fjs/basen/base64/proof.f.d.mts +3 -1
  14. package/fjs/basen/base64/proof.f.mjs +7 -4
  15. package/fjs/basen/cbase32/proof.f.d.mts +3 -1
  16. package/fjs/basen/cbase32/proof.f.mjs +3 -1
  17. package/fjs/bnf/data/module.f.d.mts +32 -6
  18. package/fjs/bnf/data/module.f.mjs +112 -7
  19. package/fjs/bnf/data/proof.f.d.mts +2 -0
  20. package/fjs/bnf/data/proof.f.mjs +74 -4
  21. package/fjs/bnf/data/types.d.ts +20 -2
  22. package/fjs/bnf/descent/module.f.d.mts +34 -5
  23. package/fjs/bnf/descent/module.f.mjs +176 -54
  24. package/fjs/bnf/descent/proof.f.d.mts +3 -0
  25. package/fjs/bnf/descent/proof.f.mjs +189 -27
  26. package/fjs/bnf/descent/types.d.ts +24 -18
  27. package/fjs/bnf/ll1/module.f.d.mts +74 -6
  28. package/fjs/bnf/ll1/module.f.mjs +297 -95
  29. package/fjs/bnf/ll1/proof.f.d.mts +17 -2
  30. package/fjs/bnf/ll1/proof.f.mjs +372 -137
  31. package/fjs/bnf/ll1/types.d.ts +25 -27
  32. package/fjs/bnf/matcher/module.f.d.mts +66 -0
  33. package/fjs/bnf/matcher/module.f.mjs +81 -0
  34. package/fjs/bnf/matcher/proof.f.d.mts +10 -0
  35. package/fjs/bnf/matcher/proof.f.mjs +79 -0
  36. package/fjs/bnf/matcher/types.d.ts +54 -0
  37. package/fjs/bnf/module.f.d.mts +15 -6
  38. package/fjs/bnf/module.f.mjs +52 -11
  39. package/fjs/bnf/proof.f.d.mts +2 -0
  40. package/fjs/bnf/proof.f.mjs +79 -3
  41. package/fjs/bnf/testlib.f.d.mts +31 -0
  42. package/fjs/bnf/testlib.f.mjs +80 -0
  43. package/fjs/bnf/token_symbol/module.f.d.mts +4 -3
  44. package/fjs/bnf/token_symbol/module.f.mjs +7 -6
  45. package/fjs/bnf/token_symbol/proof.f.mjs +5 -2
  46. package/fjs/bnf/token_symbol/types.d.ts +2 -2
  47. package/fjs/bnf/types.d.ts +10 -3
  48. package/fjs/cas/cli/module.f.d.mts +1 -1
  49. package/fjs/cas/cli/module.f.mjs +14 -20
  50. package/fjs/cas/cli/proof.f.d.mts +4 -4
  51. package/fjs/cas/cli/proof.f.mjs +47 -34
  52. package/fjs/cas/evo/module.f.d.mts +71 -31
  53. package/fjs/cas/evo/module.f.mjs +223 -138
  54. package/fjs/cas/evo/proof.f.d.mts +10 -1
  55. package/fjs/cas/evo/proof.f.mjs +311 -226
  56. package/fjs/cas/evo/types.d.ts +45 -9
  57. package/fjs/cas/module.f.d.mts +18 -32
  58. package/fjs/cas/module.f.mjs +164 -176
  59. package/fjs/cas/proof.f.d.mts +11 -8
  60. package/fjs/cas/proof.f.mjs +259 -147
  61. package/fjs/cas/types.d.ts +24 -10
  62. package/fjs/ci/common/module.f.d.mts +1 -1
  63. package/fjs/ci/common/module.f.mjs +1 -0
  64. package/fjs/ci/config/module.f.d.mts +3 -3
  65. package/fjs/ci/config/module.f.mjs +3 -3
  66. package/fjs/ci/module.f.d.mts +5 -5
  67. package/fjs/ci/module.f.mjs +8 -7
  68. package/fjs/ci/nix/module.f.d.mts +7 -5
  69. package/fjs/ci/nix/module.f.mjs +13 -12
  70. package/fjs/ci/nix/proof.f.d.mts +2 -0
  71. package/fjs/ci/nix/proof.f.mjs +4 -4
  72. package/fjs/ci/proof.f.d.mts +4 -2
  73. package/fjs/ci/proof.f.mjs +13 -8
  74. package/fjs/cli/module.f.d.mts +4 -6
  75. package/fjs/cli/module.f.mjs +4 -8
  76. package/fjs/cli/proof.f.d.mts +4 -2
  77. package/fjs/cli/proof.f.mjs +21 -18
  78. package/fjs/cli/types.d.ts +2 -3
  79. package/fjs/common/monoid/module.f.d.mts +70 -12
  80. package/fjs/common/monoid/module.f.mjs +177 -14
  81. package/fjs/common/monoid/proof.f.d.mts +12 -1
  82. package/fjs/common/monoid/proof.f.mjs +88 -4
  83. package/fjs/common/monoid/types.d.ts +23 -0
  84. package/fjs/crypto/hmac/module.f.mjs +2 -2
  85. package/fjs/crypto/secp/proof.f.d.mts +3 -1
  86. package/fjs/crypto/secp/proof.f.mjs +3 -1
  87. package/fjs/crypto/sha2/module.f.mjs +3 -1
  88. package/fjs/crypto/sha2/proof.f.d.mts +4 -1
  89. package/fjs/crypto/sha2/proof.f.mjs +27 -1
  90. package/fjs/crypto/sha2/types.d.ts +11 -0
  91. package/fjs/crypto/sign/module.f.mjs +2 -2
  92. package/fjs/crypto/vdf/module.f.d.mts +23 -4
  93. package/fjs/crypto/vdf/module.f.mjs +6 -4
  94. package/fjs/dev/module.f.d.mts +17 -5
  95. package/fjs/dev/module.f.mjs +60 -30
  96. package/fjs/dev/update/module.f.d.mts +11 -3
  97. package/fjs/dev/update/module.f.mjs +16 -11
  98. package/fjs/dev/update/proof.f.d.mts +4 -3
  99. package/fjs/dev/update/proof.f.mjs +11 -7
  100. package/fjs/djs/module.f.d.mts +13 -5
  101. package/fjs/djs/module.f.mjs +31 -16
  102. package/fjs/djs/parser/module.f.d.mts +16 -3
  103. package/fjs/djs/parser/module.f.mjs +135 -16
  104. package/fjs/djs/parser/proof.f.d.mts +8 -1
  105. package/fjs/djs/parser/proof.f.mjs +287 -13
  106. package/fjs/djs/parser/types.d.ts +7 -1
  107. package/fjs/djs/proof.f.d.mts +20 -1
  108. package/fjs/djs/proof.f.mjs +190 -12
  109. package/fjs/djs/serializer/module.f.d.mts +25 -8
  110. package/fjs/djs/serializer/module.f.mjs +66 -19
  111. package/fjs/djs/serializer/proof.f.d.mts +5 -0
  112. package/fjs/djs/serializer/proof.f.mjs +23 -1
  113. package/fjs/djs/tokenizer/module.f.d.mts +17 -5
  114. package/fjs/djs/tokenizer/module.f.mjs +120 -73
  115. package/fjs/djs/tokenizer/proof.f.d.mts +3 -0
  116. package/fjs/djs/tokenizer/proof.f.mjs +86 -67
  117. package/fjs/djs/transpiler/module.f.d.mts +13 -19
  118. package/fjs/djs/transpiler/module.f.mjs +79 -72
  119. package/fjs/djs/transpiler/types.d.ts +29 -0
  120. package/fjs/djs/types.d.ts +7 -1
  121. package/fjs/effects/list/module.f.d.mts +23 -12
  122. package/fjs/effects/list/module.f.mjs +16 -12
  123. package/fjs/effects/list/types.d.ts +27 -7
  124. package/fjs/effects/memory/module.f.d.mts +6 -3
  125. package/fjs/effects/memory/module.f.mjs +7 -7
  126. package/fjs/effects/memory/proof.f.d.mts +4 -0
  127. package/fjs/effects/memory/proof.f.mjs +18 -9
  128. package/fjs/effects/memory/types.d.ts +4 -3
  129. package/fjs/effects/mock/module.f.d.mts +28 -4
  130. package/fjs/effects/mock/module.f.mjs +39 -5
  131. package/fjs/effects/mock/types.d.ts +10 -1
  132. package/fjs/effects/module.d.mts +12 -2
  133. package/fjs/effects/module.f.d.mts +469 -281
  134. package/fjs/effects/module.f.mjs +538 -299
  135. package/fjs/effects/module.mjs +11 -2
  136. package/fjs/effects/node/memory/module.d.mts +7 -2
  137. package/fjs/effects/node/memory/module.mjs +9 -5
  138. package/fjs/effects/node/memory/proof.d.mts +2 -0
  139. package/fjs/effects/node/memory/proof.mjs +12 -5
  140. package/fjs/effects/node/module.d.mts +8 -2
  141. package/fjs/effects/node/module.f.d.mts +183 -43
  142. package/fjs/effects/node/module.f.mjs +260 -62
  143. package/fjs/effects/node/module.mjs +61 -50
  144. package/fjs/effects/node/proof.f.d.mts +28 -2
  145. package/fjs/effects/node/proof.f.mjs +161 -42
  146. package/fjs/effects/node/types.d.ts +106 -18
  147. package/fjs/effects/node/virtual/module.f.d.mts +21 -4
  148. package/fjs/effects/node/virtual/module.f.mjs +113 -70
  149. package/fjs/effects/node/virtual/proof.f.d.mts +31 -2
  150. package/fjs/effects/node/virtual/proof.f.mjs +201 -8
  151. package/fjs/effects/proof.f.d.mts +69 -34
  152. package/fjs/effects/proof.f.mjs +413 -130
  153. package/fjs/effects/types.d.ts +161 -33
  154. package/fjs/emergent_testing/all.test.d.mts +8 -0
  155. package/fjs/emergent_testing/all.test.mjs +14 -0
  156. package/fjs/emergent_testing/module.f.d.mts +22 -10
  157. package/fjs/emergent_testing/module.f.mjs +119 -85
  158. package/fjs/emergent_testing/proof.f.d.mts +21 -7
  159. package/fjs/emergent_testing/proof.f.mjs +169 -35
  160. package/fjs/emergent_testing/types.d.ts +22 -4
  161. package/fjs/fsc/bnf.f.d.mts +3 -0
  162. package/fjs/fsc/bnf.f.mjs +4 -1
  163. package/fjs/fsc/json.f.d.mts +3 -0
  164. package/fjs/fsc/json.f.mjs +4 -1
  165. package/fjs/fsc/module.f.d.mts +9 -0
  166. package/fjs/fsc/module.f.mjs +5 -3
  167. package/fjs/fsm/module.f.d.mts +14 -4
  168. package/fjs/fsm/module.f.mjs +54 -37
  169. package/fjs/fsm/proof.f.d.mts +5 -0
  170. package/fjs/fsm/proof.f.mjs +87 -115
  171. package/fjs/js/keywords/module.f.d.mts +52 -0
  172. package/fjs/js/keywords/module.f.mjs +72 -0
  173. package/fjs/{emergent_testing/scenarios/return-value.pass.d.ts → js/keywords/proof.f.d.mts} +1 -1
  174. package/fjs/js/keywords/proof.f.mjs +13 -0
  175. package/fjs/js/tokenizer/module.f.d.mts +30 -3
  176. package/fjs/js/tokenizer/module.f.mjs +161 -211
  177. package/fjs/js/tokenizer/proof.f.d.mts +1 -0
  178. package/fjs/js/tokenizer/proof.f.mjs +54 -24
  179. package/fjs/js/tokenizer/types.d.ts +33 -24
  180. package/fjs/mcp/cas/module.f.d.mts +1 -6
  181. package/fjs/mcp/cas/module.f.mjs +55 -51
  182. package/fjs/mcp/cas/proof.f.d.mts +15 -0
  183. package/fjs/mcp/cas/proof.f.mjs +174 -0
  184. package/fjs/mcp/evo/module.f.d.mts +19 -10
  185. package/fjs/mcp/evo/module.f.mjs +48 -27
  186. package/fjs/mcp/evo/proof.f.d.mts +6 -1
  187. package/fjs/mcp/evo/proof.f.mjs +115 -31
  188. package/fjs/mcp/module.f.d.mts +39 -4
  189. package/fjs/mcp/module.f.mjs +14 -12
  190. package/fjs/mcp/proof.f.d.mts +13 -1
  191. package/fjs/mcp/proof.f.mjs +120 -61
  192. package/fjs/media/html/module.f.d.mts +12 -0
  193. package/fjs/media/html/module.f.mjs +7 -5
  194. package/fjs/media/html/proof.f.d.mts +3 -0
  195. package/fjs/media/html/proof.f.mjs +4 -1
  196. package/fjs/media/json/extended/module.f.d.mts +82 -0
  197. package/fjs/media/json/extended/module.f.mjs +153 -0
  198. package/fjs/media/json/extended/proof.f.d.mts +42 -0
  199. package/fjs/media/json/extended/proof.f.mjs +127 -0
  200. package/fjs/media/json/extended/types.d.ts +23 -0
  201. package/fjs/media/json/module.f.d.mts +8 -2
  202. package/fjs/media/json/module.f.mjs +43 -41
  203. package/fjs/media/json/number/module.f.d.mts +59 -0
  204. package/fjs/media/json/number/module.f.mjs +136 -0
  205. package/fjs/media/json/number/proof.f.d.mts +24 -0
  206. package/fjs/media/json/number/proof.f.mjs +86 -0
  207. package/fjs/media/json/number/types.d.ts +28 -0
  208. package/fjs/media/json/parser/module.f.d.mts +25 -13
  209. package/fjs/media/json/parser/module.f.mjs +133 -72
  210. package/fjs/media/json/parser/proof.f.d.mts +5 -0
  211. package/fjs/media/json/parser/proof.f.mjs +31 -1
  212. package/fjs/media/json/parser/types.d.ts +38 -14
  213. package/fjs/media/json/rtti/module.f.d.mts +1 -1
  214. package/fjs/media/json/rtti/module.f.mjs +1 -1
  215. package/fjs/media/json/rtti/proof.f.d.mts +3 -0
  216. package/fjs/media/json/rtti/proof.f.mjs +12 -12
  217. package/fjs/media/json/schema/module.f.d.mts +61 -27
  218. package/fjs/media/json/schema/module.f.mjs +218 -63
  219. package/fjs/media/json/schema/proof.f.d.mts +41 -1
  220. package/fjs/media/json/schema/proof.f.mjs +220 -9
  221. package/fjs/media/json/serializer/module.f.d.mts +44 -0
  222. package/fjs/media/json/serializer/module.f.mjs +71 -9
  223. package/fjs/media/json/tokenizer/module.f.d.mts +8 -0
  224. package/fjs/media/json/tokenizer/module.f.mjs +31 -8
  225. package/fjs/media/json/tokenizer/proof.f.d.mts +6 -0
  226. package/fjs/media/json/tokenizer/proof.f.mjs +62 -21
  227. package/fjs/media/json/types.d.ts +36 -10
  228. package/fjs/media/lock/module.f.d.mts +100 -0
  229. package/fjs/media/lock/module.f.mjs +125 -0
  230. package/fjs/media/lock/proof.f.d.mts +33 -0
  231. package/fjs/media/lock/proof.f.mjs +196 -0
  232. package/fjs/media/lock/types.d.ts +15 -0
  233. package/fjs/media/module.f.d.mts +6 -5
  234. package/fjs/media/module.f.mjs +8 -7
  235. package/fjs/media/nix/module.f.d.mts +13 -0
  236. package/fjs/media/nix/module.f.mjs +4 -2
  237. package/fjs/media/nix/proof.f.d.mts +3 -0
  238. package/fjs/media/nix/proof.f.mjs +4 -1
  239. package/fjs/media/note/module.f.d.mts +121 -0
  240. package/fjs/media/note/module.f.mjs +131 -0
  241. package/fjs/media/note/proof.f.d.mts +29 -0
  242. package/fjs/media/note/proof.f.mjs +150 -0
  243. package/fjs/media/note/types.d.ts +10 -0
  244. package/fjs/media/proof.f.d.mts +4 -1
  245. package/fjs/media/proof.f.mjs +40 -21
  246. package/fjs/media/revision/module.f.d.mts +83 -7
  247. package/fjs/media/revision/module.f.mjs +127 -23
  248. package/fjs/media/revision/proof.f.d.mts +14 -0
  249. package/fjs/media/revision/proof.f.mjs +93 -2
  250. package/fjs/media/revision/types.d.ts +34 -5
  251. package/fjs/media/type/module.f.d.mts +53 -18
  252. package/fjs/media/type/module.f.mjs +87 -97
  253. package/fjs/media/type/proof.f.d.mts +17 -0
  254. package/fjs/media/type/proof.f.mjs +73 -13
  255. package/fjs/module.d.mts +5 -0
  256. package/fjs/module.f.d.mts +8 -0
  257. package/fjs/module.f.mjs +33 -10
  258. package/fjs/module.mjs +6 -0
  259. package/fjs/nanvm/proof.f.mjs +3 -3
  260. package/fjs/nanvm/rust/module.f.mjs +1 -1
  261. package/fjs/nanvm/update/module.f.d.mts +4 -4
  262. package/fjs/nanvm/update/module.f.mjs +8 -9
  263. package/fjs/nanvm/update/proof.f.mjs +4 -3
  264. package/fjs/path/module.f.d.mts +8 -0
  265. package/fjs/path/module.f.mjs +4 -2
  266. package/fjs/proof.f.d.mts +7 -3
  267. package/fjs/proof.f.mjs +41 -12
  268. package/fjs/protocol/json_rpc/module.f.d.mts +3 -3
  269. package/fjs/protocol/json_rpc/module.f.mjs +10 -7
  270. package/fjs/protocol/json_rpc/proof.f.d.mts +6 -0
  271. package/fjs/protocol/json_rpc/proof.f.mjs +26 -5
  272. package/fjs/protocol/mcp/module.f.d.mts +10 -13
  273. package/fjs/protocol/mcp/module.f.mjs +74 -58
  274. package/fjs/protocol/mcp/proof.f.d.mts +16 -3
  275. package/fjs/protocol/mcp/proof.f.mjs +224 -69
  276. package/fjs/protocol/mcp/stdio/module.f.d.mts +17 -11
  277. package/fjs/protocol/mcp/stdio/module.f.mjs +39 -33
  278. package/fjs/protocol/mcp/stdio/proof.f.d.mts +5 -3
  279. package/fjs/protocol/mcp/stdio/proof.f.mjs +46 -13
  280. package/fjs/protocol/mcp/stdio/types.d.ts +14 -0
  281. package/fjs/protocol/mcp/types.d.ts +17 -6
  282. package/fjs/sul/id/module.f.d.mts +4 -0
  283. package/fjs/sul/id/module.f.mjs +6 -6
  284. package/fjs/sul/level/hash/module.f.d.mts +4 -1
  285. package/fjs/sul/level/hash/module.f.mjs +6 -4
  286. package/fjs/sul/level/hash/proof.f.d.mts +4 -0
  287. package/fjs/sul/level/hash/proof.f.mjs +7 -4
  288. package/fjs/sul/level/literal/module.f.d.mts +4 -1
  289. package/fjs/sul/level/literal/module.f.mjs +4 -3
  290. package/fjs/sul/level/literal/proof.f.d.mts +3 -0
  291. package/fjs/sul/level/literal/proof.f.mjs +4 -1
  292. package/fjs/sul/module.f.d.mts +5 -3
  293. package/fjs/sul/module.f.mjs +23 -17
  294. package/fjs/sul/proof.f.d.mts +4 -0
  295. package/fjs/sul/proof.f.mjs +5 -2
  296. package/fjs/text/ascii/module.f.d.mts +26 -0
  297. package/fjs/text/ascii/module.f.mjs +49 -1
  298. package/fjs/text/ascii/proof.f.d.mts +10 -0
  299. package/fjs/text/ascii/proof.f.mjs +33 -1
  300. package/fjs/text/code_point/module.f.d.mts +29 -3
  301. package/fjs/text/code_point/module.f.mjs +32 -9
  302. package/fjs/text/code_point/proof.f.d.mts +2 -0
  303. package/fjs/text/code_point/proof.f.mjs +39 -0
  304. package/fjs/text/module.f.d.mts +4 -2
  305. package/fjs/text/module.f.mjs +4 -3
  306. package/fjs/text/proof.f.d.mts +3 -0
  307. package/fjs/text/proof.f.mjs +4 -1
  308. package/fjs/text/sgr/module.f.d.mts +6 -5
  309. package/fjs/text/sgr/module.f.mjs +8 -8
  310. package/fjs/text/sgr/proof.f.d.mts +3 -0
  311. package/fjs/text/sgr/proof.f.mjs +4 -1
  312. package/fjs/text/utf16/module.f.d.mts +5 -1
  313. package/fjs/text/utf16/module.f.mjs +38 -35
  314. package/fjs/text/utf16/proof.f.d.mts +3 -1
  315. package/fjs/text/utf16/proof.f.mjs +19 -2
  316. package/fjs/text/utf8/module.f.d.mts +9 -5
  317. package/fjs/text/utf8/module.f.mjs +20 -20
  318. package/fjs/types/array/module.f.d.mts +2 -1
  319. package/fjs/types/array/module.f.mjs +16 -4
  320. package/fjs/types/bigfloat/module.f.d.mts +21 -1
  321. package/fjs/types/bigfloat/module.f.mjs +33 -7
  322. package/fjs/types/bigfloat/proof.f.d.mts +1 -0
  323. package/fjs/types/bigfloat/proof.f.mjs +46 -0
  324. package/fjs/types/bigint/module.f.d.mts +4 -0
  325. package/fjs/types/bigint/module.f.mjs +4 -3
  326. package/fjs/types/bit_vec/module.f.d.mts +10 -16
  327. package/fjs/types/bit_vec/module.f.mjs +99 -95
  328. package/fjs/types/bit_vec/proof.f.d.mts +6 -0
  329. package/fjs/types/bit_vec/proof.f.mjs +31 -5
  330. package/fjs/types/btree/find/module.f.d.mts +5 -1
  331. package/fjs/types/btree/find/module.f.mjs +5 -5
  332. package/fjs/types/btree/find/proof.f.d.mts +5 -1
  333. package/fjs/types/btree/find/proof.f.mjs +5 -3
  334. package/fjs/types/btree/module.f.d.mts +3 -0
  335. package/fjs/types/btree/module.f.mjs +3 -2
  336. package/fjs/types/btree/proof.f.d.mts +5 -1
  337. package/fjs/types/btree/proof.f.mjs +5 -3
  338. package/fjs/types/btree/remove/module.f.d.mts +11 -0
  339. package/fjs/types/btree/remove/module.f.mjs +10 -10
  340. package/fjs/types/btree/remove/proof.f.d.mts +3 -0
  341. package/fjs/types/btree/remove/proof.f.mjs +4 -1
  342. package/fjs/types/btree/set/module.f.d.mts +9 -0
  343. package/fjs/types/btree/set/module.f.mjs +14 -17
  344. package/fjs/types/btree/set/proof.f.d.mts +3 -0
  345. package/fjs/types/btree/set/proof.f.mjs +16 -1
  346. package/fjs/types/btree/types/module.f.d.mts +2 -1
  347. package/fjs/types/btree/types/module.f.mjs +2 -1
  348. package/fjs/types/byte_set/module.f.d.mts +20 -4
  349. package/fjs/types/byte_set/module.f.mjs +18 -8
  350. package/fjs/types/byte_set/proof.f.d.mts +3 -1
  351. package/fjs/types/byte_set/proof.f.mjs +10 -8
  352. package/fjs/types/function/compare/module.f.d.mts +3 -2
  353. package/fjs/types/function/compare/module.f.mjs +13 -5
  354. package/fjs/types/function/module.f.d.mts +8 -1
  355. package/fjs/types/function/module.f.mjs +8 -1
  356. package/fjs/types/function/operator/module.f.d.mts +2 -1
  357. package/fjs/types/function/operator/module.f.mjs +2 -2
  358. package/fjs/types/list/module.f.d.mts +10 -3
  359. package/fjs/types/list/module.f.mjs +6 -4
  360. package/fjs/types/list/proof.f.d.mts +4 -1
  361. package/fjs/types/list/proof.f.mjs +4 -2
  362. package/fjs/types/nibble_set/module.f.d.mts +2 -1
  363. package/fjs/types/nibble_set/module.f.mjs +2 -2
  364. package/fjs/types/nominal/module.f.d.mts +2 -1
  365. package/fjs/types/nominal/module.f.mjs +2 -1
  366. package/fjs/types/nullable/module.f.d.mts +26 -6
  367. package/fjs/types/nullable/module.f.mjs +25 -6
  368. package/fjs/types/nullable/proof.f.d.mts +4 -0
  369. package/fjs/types/nullable/proof.f.mjs +15 -0
  370. package/fjs/types/number/module.f.d.mts +4 -0
  371. package/fjs/types/number/module.f.mjs +4 -3
  372. package/fjs/types/object/module.f.d.mts +26 -4
  373. package/fjs/types/object/module.f.mjs +26 -7
  374. package/fjs/types/object/proof.f.d.mts +5 -2
  375. package/fjs/types/object/proof.f.mjs +6 -3
  376. package/fjs/types/object/structurally_same/module.f.d.mts +39 -0
  377. package/fjs/types/object/structurally_same/module.f.mjs +59 -0
  378. package/fjs/types/object/structurally_same/proof.f.d.mts +6 -0
  379. package/fjs/types/object/structurally_same/proof.f.mjs +73 -0
  380. package/fjs/types/ordered_map/module.f.d.mts +5 -0
  381. package/fjs/types/ordered_map/module.f.mjs +5 -4
  382. package/fjs/types/ordered_map/proof.f.d.mts +3 -0
  383. package/fjs/types/ordered_map/proof.f.mjs +4 -1
  384. package/fjs/types/patricia_trie/module.f.d.mts +2 -1
  385. package/fjs/types/patricia_trie/module.f.mjs +27 -12
  386. package/fjs/types/patricia_trie/proof.f.d.mts +3 -0
  387. package/fjs/types/patricia_trie/proof.f.mjs +4 -1
  388. package/fjs/types/prime_field/module.f.d.mts +3 -1
  389. package/fjs/types/prime_field/module.f.mjs +3 -2
  390. package/fjs/types/range/module.f.d.mts +2 -1
  391. package/fjs/types/range/module.f.mjs +2 -2
  392. package/fjs/types/range_map/module.f.d.mts +6 -0
  393. package/fjs/types/range_map/module.f.mjs +6 -9
  394. package/fjs/types/range_map/proof.f.d.mts +5 -1
  395. package/fjs/types/range_map/proof.f.mjs +5 -3
  396. package/fjs/types/range_set/module.f.d.mts +5 -0
  397. package/fjs/types/range_set/module.f.mjs +1 -0
  398. package/fjs/types/range_set/proof.f.d.mts +3 -0
  399. package/fjs/types/range_set/proof.f.mjs +4 -1
  400. package/fjs/types/result/module.d.mts +8 -0
  401. package/fjs/types/result/module.f.d.mts +37 -7
  402. package/fjs/types/result/module.f.mjs +38 -8
  403. package/fjs/types/result/module.mjs +9 -1
  404. package/fjs/types/result/proof.f.d.mts +5 -0
  405. package/fjs/types/result/proof.f.mjs +22 -2
  406. package/fjs/types/rtti/common/module.f.d.mts +44 -14
  407. package/fjs/types/rtti/common/module.f.mjs +42 -36
  408. package/fjs/types/rtti/common/proof.f.d.mts +4 -0
  409. package/fjs/types/rtti/common/proof.f.mjs +10 -7
  410. package/fjs/types/rtti/data/module.f.d.mts +134 -0
  411. package/fjs/types/rtti/data/module.f.mjs +1053 -0
  412. package/fjs/types/rtti/data/proof.f.d.mts +76 -0
  413. package/fjs/types/rtti/data/proof.f.mjs +589 -0
  414. package/fjs/types/rtti/data/types.d.ts +83 -0
  415. package/fjs/types/rtti/module.f.d.mts +12 -5
  416. package/fjs/types/rtti/module.f.mjs +7 -5
  417. package/fjs/types/rtti/parse/module.f.d.mts +48 -0
  418. package/fjs/types/rtti/parse/module.f.mjs +45 -34
  419. package/fjs/types/rtti/parse/proof.f.d.mts +3 -2
  420. package/fjs/types/rtti/parse/proof.f.mjs +51 -52
  421. package/fjs/types/rtti/proof.f.d.mts +3 -1
  422. package/fjs/types/rtti/proof.f.mjs +6 -2
  423. package/fjs/types/rtti/ts/module.f.d.mts +68 -9
  424. package/fjs/types/rtti/ts/module.f.mjs +258 -30
  425. package/fjs/types/rtti/ts/proof.f.d.mts +44 -0
  426. package/fjs/types/rtti/ts/proof.f.mjs +152 -4
  427. package/fjs/types/rtti/ts/types.d.ts +25 -1
  428. package/fjs/types/rtti/types.d.ts +40 -0
  429. package/fjs/types/sorted_list/module.f.d.mts +4 -1
  430. package/fjs/types/sorted_list/module.f.mjs +21 -12
  431. package/fjs/types/sorted_list/proof.f.d.mts +3 -1
  432. package/fjs/types/sorted_list/proof.f.mjs +3 -1
  433. package/fjs/types/sorted_set/module.f.d.mts +49 -1
  434. package/fjs/types/sorted_set/module.f.mjs +26 -2
  435. package/fjs/types/sorted_set/proof.f.d.mts +4 -1
  436. package/fjs/types/sorted_set/proof.f.mjs +19 -2
  437. package/fjs/types/string/module.f.d.mts +4 -0
  438. package/fjs/types/string/module.f.mjs +4 -3
  439. package/fjs/types/string_set/module.f.d.mts +3 -1
  440. package/fjs/types/string_set/module.f.mjs +3 -2
  441. package/fjs/types/ts/module.f.d.mts +2 -0
  442. package/fjs/types/ts/module.f.mjs +3 -3
  443. package/fjs/types/ts/proof.f.d.mts +1 -0
  444. package/fjs/types/ts/proof.f.mjs +5 -0
  445. package/fjs/types/ts/types.d.ts +6 -1
  446. package/fjs/types/uint8array/module.f.d.mts +13 -2
  447. package/fjs/types/uint8array/module.f.mjs +20 -15
  448. package/fjs/website/module.f.d.mts +5 -2
  449. package/fjs/website/module.f.mjs +6 -8
  450. package/fjs/website/proof.f.mjs +2 -1
  451. package/package.json +3 -3
  452. package/fjs/asn.1/types.js +0 -6
  453. package/fjs/asserts/types.js +0 -6
  454. package/fjs/basen/types.js +0 -6
  455. package/fjs/bnf/data/types.js +0 -6
  456. package/fjs/bnf/descent/types.js +0 -6
  457. package/fjs/bnf/ll1/types.js +0 -6
  458. package/fjs/bnf/token_symbol/types.js +0 -6
  459. package/fjs/bnf/types.js +0 -6
  460. package/fjs/cas/evo/types.js +0 -7
  461. package/fjs/cas/types.js +0 -6
  462. package/fjs/ci/common/types.js +0 -1
  463. package/fjs/ci/nix/types.js +0 -6
  464. package/fjs/ci/types.js +0 -6
  465. package/fjs/cli/types.js +0 -6
  466. package/fjs/common/monoid/types.js +0 -6
  467. package/fjs/crypto/pow/types.js +0 -6
  468. package/fjs/crypto/secp/types.js +0 -6
  469. package/fjs/crypto/sha2/types.js +0 -6
  470. package/fjs/crypto/sign/types.js +0 -6
  471. package/fjs/crypto/vdf/types.js +0 -6
  472. package/fjs/dev/package_json/module.f.d.mts +0 -32
  473. package/fjs/dev/package_json/module.f.mjs +0 -37
  474. package/fjs/dev/package_json/proof.f.d.mts +0 -6
  475. package/fjs/dev/package_json/proof.f.mjs +0 -32
  476. package/fjs/dev/types.js +0 -6
  477. package/fjs/djs/ast/types.js +0 -8
  478. package/fjs/djs/parser/types.js +0 -7
  479. package/fjs/djs/tokenizer/types.js +0 -7
  480. package/fjs/djs/types.js +0 -7
  481. package/fjs/effects/eff/module.f.d.mts +0 -10
  482. package/fjs/effects/eff/module.f.mjs +0 -68
  483. package/fjs/effects/eff/proof.f.d.mts +0 -12
  484. package/fjs/effects/eff/proof.f.mjs +0 -66
  485. package/fjs/effects/eff/types.d.ts +0 -71
  486. package/fjs/effects/eff/types.js +0 -6
  487. package/fjs/effects/list/types.js +0 -6
  488. package/fjs/effects/memory/types.js +0 -6
  489. package/fjs/effects/mock/types.js +0 -6
  490. package/fjs/effects/node/types.js +0 -6
  491. package/fjs/effects/node/virtual/types.js +0 -7
  492. package/fjs/effects/types.js +0 -6
  493. package/fjs/emergent_testing/all.test.d.ts +0 -1
  494. package/fjs/emergent_testing/all.test.js +0 -5
  495. package/fjs/emergent_testing/scenarios/all.d.ts +0 -1
  496. package/fjs/emergent_testing/scenarios/all.js +0 -1
  497. package/fjs/emergent_testing/scenarios/async-subtests.fail.d.ts +0 -6
  498. package/fjs/emergent_testing/scenarios/async-subtests.fail.js +0 -9
  499. package/fjs/emergent_testing/scenarios/async-subtests.pass.d.ts +0 -6
  500. package/fjs/emergent_testing/scenarios/async-subtests.pass.js +0 -9
  501. package/fjs/emergent_testing/scenarios/async.fail.d.ts +0 -3
  502. package/fjs/emergent_testing/scenarios/async.fail.js +0 -6
  503. package/fjs/emergent_testing/scenarios/async.pass.d.ts +0 -3
  504. package/fjs/emergent_testing/scenarios/async.pass.js +0 -5
  505. package/fjs/emergent_testing/scenarios/fail.fail.d.ts +0 -3
  506. package/fjs/emergent_testing/scenarios/fail.fail.js +0 -3
  507. package/fjs/emergent_testing/scenarios/return-value.pass.js +0 -4
  508. package/fjs/emergent_testing/scenarios/thenable.pass.d.ts +0 -5
  509. package/fjs/emergent_testing/scenarios/thenable.pass.js +0 -11
  510. package/fjs/emergent_testing/scenarios/thenable2.pass.d.ts +0 -5
  511. package/fjs/emergent_testing/scenarios/thenable2.pass.js +0 -3
  512. package/fjs/emergent_testing/scenarios/throw.pass.d.ts +0 -5
  513. package/fjs/emergent_testing/scenarios/throw.pass.js +0 -3
  514. package/fjs/emergent_testing/types.js +0 -6
  515. package/fjs/js/tokenizer/types.js +0 -6
  516. package/fjs/media/html/types.js +0 -6
  517. package/fjs/media/json/parser/types.js +0 -6
  518. package/fjs/media/json/tokenizer/types.js +0 -6
  519. package/fjs/media/json/types.js +0 -13
  520. package/fjs/media/nix/types.js +0 -6
  521. package/fjs/media/revision/types.js +0 -8
  522. package/fjs/media/type/types.js +0 -6
  523. package/fjs/media/types.js +0 -7
  524. package/fjs/nanvm/types.js +0 -11
  525. package/fjs/protocol/json_rpc/types.js +0 -8
  526. package/fjs/protocol/mcp/types.js +0 -8
  527. package/fjs/sul/id/types.js +0 -6
  528. package/fjs/sul/level/hash/types.js +0 -6
  529. package/fjs/sul/level/literal/types.js +0 -6
  530. package/fjs/sul/types.js +0 -6
  531. package/fjs/text/sgr/types.js +0 -6
  532. package/fjs/text/types.js +0 -6
  533. package/fjs/text/utf16/types.js +0 -6
  534. package/fjs/text/utf8/types.js +0 -6
  535. package/fjs/types/array/types.js +0 -6
  536. package/fjs/types/bigfloat/types.js +0 -6
  537. package/fjs/types/bigint/types.js +0 -6
  538. package/fjs/types/bit_vec/types.js +0 -6
  539. package/fjs/types/btree/find/types.js +0 -6
  540. package/fjs/types/btree/types/types.js +0 -6
  541. package/fjs/types/byte_set/types.js +0 -6
  542. package/fjs/types/function/compare/types.js +0 -6
  543. package/fjs/types/function/operator/types.js +0 -6
  544. package/fjs/types/function/types.js +0 -6
  545. package/fjs/types/list/types.js +0 -6
  546. package/fjs/types/nibble_set/types.js +0 -6
  547. package/fjs/types/nominal/types.js +0 -6
  548. package/fjs/types/nullable/types.js +0 -6
  549. package/fjs/types/object/types.js +0 -8
  550. package/fjs/types/option/types.js +0 -6
  551. package/fjs/types/ordered_map/types.js +0 -6
  552. package/fjs/types/patricia_trie/types.js +0 -6
  553. package/fjs/types/phantom/types.js +0 -11
  554. package/fjs/types/prime_field/types.js +0 -6
  555. package/fjs/types/range/types.js +0 -6
  556. package/fjs/types/range_map/types.js +0 -6
  557. package/fjs/types/result/types.js +0 -6
  558. package/fjs/types/rtti/common/types.js +0 -1
  559. package/fjs/types/rtti/parse/types.js +0 -1
  560. package/fjs/types/rtti/ts/types.js +0 -1
  561. package/fjs/types/rtti/types.js +0 -1
  562. package/fjs/types/rtti/validate/module.f.d.mts +0 -6
  563. package/fjs/types/rtti/validate/module.f.mjs +0 -169
  564. package/fjs/types/rtti/validate/proof.f.d.mts +0 -125
  565. package/fjs/types/rtti/validate/proof.f.mjs +0 -437
  566. package/fjs/types/rtti/validate/types.d.ts +0 -6
  567. package/fjs/types/rtti/validate/types.js +0 -1
  568. package/fjs/types/sorted_list/types.js +0 -6
  569. package/fjs/types/sorted_set/types.js +0 -6
  570. package/fjs/types/string_set/types.js +0 -6
  571. package/fjs/types/ts/types.js +0 -8
@@ -0,0 +1,150 @@
1
+ import { assert, assertEq } from '../../asserts/module.f.mjs'
2
+ import { dialect, mediaType, decodeText, encodeText, noteDialect, priorities, validate } from './module.f.mjs'
3
+ import { dialect as lockDialect } from '../lock/module.f.mjs'
4
+
5
+ export const proof = {
6
+ dialectAndMediaType: () => {
7
+ assertEq(dialect, 'vnd.fjs.note')
8
+ assertEq(mediaType, 'application/vnd.fjs.note+json')
9
+ },
10
+
11
+ // The published scale, most urgent first — `todo/README.md`'s vocabulary.
12
+ priorityScale: () => {
13
+ assertEq(priorities.join(','), 'P1,P2,P3,P4,P5')
14
+ },
15
+
16
+ validate: {
17
+ // The ordinary case: the tag and the text.
18
+ minimalNoteAccepted: () => {
19
+ const r = validate({ dialect, text: 'buy milk' })
20
+ assert(r[0] === 'ok', ['expected ok', r])
21
+ assertEq(r[1].text, 'buy milk')
22
+ },
23
+
24
+ // `text` may be empty — required rather than optional, so an absent
25
+ // text and an empty one are not two spellings of one blob.
26
+ emptyTextAccepted: () => {
27
+ const [t] = validate({ dialect, text: '' })
28
+ assertEq(t, 'ok')
29
+ },
30
+
31
+ // `text` is required: a blob carrying only the tag is not a note.
32
+ missingTextRejected: () => {
33
+ const [t] = validate({ dialect })
34
+ assertEq(t, 'error')
35
+ },
36
+
37
+ // The text is a string, nothing else.
38
+ nonStringTextRejected: () => {
39
+ const [t] = validate({ dialect, text: 42 })
40
+ assertEq(t, 'error')
41
+ },
42
+
43
+ // Dependencies are subject identity strings, unconstrained like
44
+ // `vnd.fjs.revision`'s `subject` — no semantic check applies. The
45
+ // text may reference them by index (`[0]`, `[1]`), which is a
46
+ // reading convention, not a validation rule: this blob validates the
47
+ // same with any text.
48
+ dependenciesAccepted: () => {
49
+ const r = validate({ dialect, text: 'ship it once [0] and [1] land', dependencies: ['write the spec', 'review'] })
50
+ assert(r[0] === 'ok', ['expected ok', r])
51
+ assertEq(r[1].dependencies?.length, 2)
52
+ },
53
+
54
+ // `[]` and an absent field both say "depends on nothing"; the format
55
+ // does not distinguish them, and both validate.
56
+ emptyDependenciesAccepted: () => {
57
+ const [t] = validate({ dialect, text: 'hi', dependencies: [] })
58
+ assertEq(t, 'ok')
59
+ },
60
+
61
+ // The field is a list of strings, nothing else.
62
+ nonArrayDependenciesRejected: () => {
63
+ const [t] = validate({ dialect, text: 'hi', dependencies: 'write the spec' })
64
+ assertEq(t, 'error')
65
+ },
66
+ nonStringDependencyRejected: () => {
67
+ const [t] = validate({ dialect, text: 'hi', dependencies: [42] })
68
+ assertEq(t, 'error')
69
+ },
70
+
71
+ // A priority is one of the closed `priorities` literals — the
72
+ // author's urgency decision, enforced entirely structurally.
73
+ priorityAccepted: () => {
74
+ const r = validate({ dialect, text: 'fix the build', priority: 'P1' })
75
+ assert(r[0] === 'ok', ['expected ok', r])
76
+ assertEq(r[1].priority, 'P1')
77
+ },
78
+
79
+ // The scale is closed: an unknown rank fails structurally rather than
80
+ // passing as a free-form string — the fail-closed widening path.
81
+ unknownPriorityRejected: () => {
82
+ const [t] = validate({ dialect, text: 'hi', priority: 'P0' })
83
+ assertEq(t, 'error')
84
+ },
85
+
86
+ // The rank is a literal, not a number: `1` is not `'P1'`.
87
+ numericPriorityRejected: () => {
88
+ const [t] = validate({ dialect, text: 'hi', priority: 1 })
89
+ assertEq(t, 'error')
90
+ },
91
+
92
+ // rtti structs are open, so unknown fields are ignored rather than
93
+ // rejected — the additive forward-compatibility path every future
94
+ // extension (title, tags, dates, …) relies on.
95
+ unknownFieldsIgnored: () => {
96
+ const [t] = validate({ dialect, text: 'call Bob', title: 'todo', done: true })
97
+ assertEq(t, 'ok')
98
+ },
99
+
100
+ // Another dialect's blob is not a note: the tag is matched as an
101
+ // exact literal.
102
+ otherDialectRejected: () => {
103
+ const [t] = validate({ dialect: lockDialect, text: 'hi' })
104
+ assertEq(t, 'error')
105
+ },
106
+ },
107
+
108
+ decodeText: {
109
+ validJson: () => {
110
+ const r = decodeText(`{"dialect":"${dialect}","text":"buy milk"}`)
111
+ assert(r[0] === 'ok', ['expected ok', r])
112
+ assertEq(r[1].text, 'buy milk')
113
+ },
114
+
115
+ // Key order carries no meaning: the JSON is parsed and the parsed
116
+ // value validated, so `dialect` need not come first.
117
+ keyOrderIndependent: () => {
118
+ const [t] = decodeText(`{"text":"hi","dialect":"${dialect}"}`)
119
+ assertEq(t, 'ok')
120
+ },
121
+
122
+ malformedJsonRejected: () => {
123
+ const [t] = decodeText('{not json')
124
+ assertEq(t, 'error')
125
+ },
126
+
127
+ ordinaryJsonRejected: () => {
128
+ const [t] = decodeText('{"hello":"world"}')
129
+ assertEq(t, 'error')
130
+ },
131
+ },
132
+
133
+ encodeText: {
134
+ // Two blobs differing only in property order converge on one byte
135
+ // sequence, so they address the same CAS blob. `dependencies` sorts
136
+ // ahead of `dialect`, and its array order is preserved — arrays retain
137
+ // their declared order under canonical serialization.
138
+ sortsPropertiesLexicographically: () => {
139
+ const decoded = decodeText(`{"text":"hi","dependencies":["b","a"],"dialect":"${dialect}"}`)
140
+ assert(decoded[0] === 'ok', ['expected ok', decoded])
141
+ assertEq(encodeText(decoded[1]), `{"dependencies":["b","a"],"dialect":"${dialect}","text":"hi"}`)
142
+ },
143
+ },
144
+
145
+ // The registry entry carries the schema's own tag; matching is exercised
146
+ // end to end through `detect` in `fjs/media/proof.f.mjs`.
147
+ noteDialectTag: () => {
148
+ assertEq(noteDialect.dialect, dialect)
149
+ },
150
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Type-level API for `fjs/media/note/module.f.mjs`: `Note` and `NoteError`.
3
+ */
4
+ import type { ValidationError } from '../../types/rtti/common/types.ts';
5
+ import type { Ts } from '../../types/rtti/ts/types.ts';
6
+ import type { noteSchema } from './module.f.mjs';
7
+ /** The TypeScript type derived from `noteSchema` — the single source of truth. */
8
+ export type Note = Ts<typeof noteSchema>;
9
+ /** Either a structural validation error or a JSON parse error message. */
10
+ export type NoteError = ValidationError | string;
@@ -4,7 +4,10 @@ export declare const proof: {
4
4
  keyOrderIndependent: () => void;
5
5
  invalidRevisionFallsThrough: () => void;
6
6
  nonHashSnapshotFallsThrough: () => void;
7
- secondDialect: () => void;
7
+ validLock: () => void;
8
+ lockAndRevisionDoNotOverlap: () => void;
9
+ nonHashLockValueFallsThrough: () => void;
10
+ validNote: () => void;
8
11
  nonVndDialectName: () => void;
9
12
  firstMatchWins: () => void;
10
13
  noDialects: () => void;
@@ -6,6 +6,8 @@ import { assertEq } from '../asserts/module.f.mjs'
6
6
  import { msb, u8ListToVec, repeat, vec8 } from '../types/bit_vec/module.f.mjs'
7
7
  import { detect, dialectEntry } from './module.f.mjs'
8
8
  import { dialect, revisionDialect } from './revision/module.f.mjs'
9
+ import { dialect as lockDialectName, lockDialect } from './lock/module.f.mjs'
10
+ import { dialect as noteDialectName, noteDialect } from './note/module.f.mjs'
9
11
  import { number, string } from '../types/rtti/module.f.mjs'
10
12
 
11
13
  // All test strings here are ASCII, so char code === UTF-8 byte value.
@@ -14,22 +16,12 @@ const utf8Bytes = s => u8ListToVec(msb)([...s].map(c => c.charCodeAt(0)))
14
16
 
15
17
  const revisionJson = `{"dialect":"${dialect}","subject":"8","parents":[],"snapshot":"8","generation":0}`
16
18
 
17
- /** @type {readonly DialectEntry[]} */
18
- const dialects = [revisionDialect]
19
-
20
- const detectRevision = detect(dialects)
21
-
22
- /**
23
- * A second dialect following the same `vnd.fjs.<name>` convention, registered
24
- * with no refinement: structure alone decides the match.
19
+ /** The three dialects `fjs/media` itself ships, in the order `fjs/mcp` registers them.
20
+ * @type {readonly DialectEntry[]}
25
21
  */
26
- const noteSchema = /** @type {const} */ ({
27
- dialect: 'vnd.fjs.note',
28
- text: string,
29
- })
22
+ const dialects = [revisionDialect, lockDialect, noteDialect]
30
23
 
31
- /** @type {DialectEntry} */
32
- const noteDialect = dialectEntry(noteSchema)
24
+ const detectRevision = detect(dialects)
33
25
 
34
26
  /** A dialect name outside `vnd.fjs.*` — registerable, and detected as itself. */
35
27
  const gadgetSchema = /** @type {const} */ ({
@@ -83,14 +75,41 @@ export const proof = {
83
75
  assertEq(m.mime_type, 'text/plain')
84
76
  },
85
77
 
86
- // A second dialect, registered by the caller, is recognized alongside the
87
- // first and an entry with no refinement matches on structure alone.
88
- secondDialect: () => {
89
- const d = detect([revisionDialect, noteDialect])
90
- assertEq(d(utf8Bytes('{"dialect":"vnd.fjs.note","text":"hi"}')).mime_type, 'application/vnd.fjs.note+json')
91
- assertEq(d(utf8Bytes(revisionJson)).mime_type, 'application/vnd.fjs.revision+json')
78
+ // A valid shared-lock blob is recognized as its own dialect, alongside the
79
+ // revision one, and reported under the derived media type.
80
+ validLock: () => {
81
+ const m = detectRevision(utf8Bytes(`{"dialect":"${lockDialectName}","lock":{"dependency":"8"}}`))
82
+ assertEq(m.type, 'text')
83
+ assertEq(m.mime_type, 'application/vnd.fjs.lock+json')
84
+ },
85
+
86
+ // The two dialects never claim each other's blobs: each schema matches its
87
+ // own `dialect` literal, so a revision carrying an inline `lock` is still a
88
+ // revision, and a lock blob is never a revision.
89
+ lockAndRevisionDoNotOverlap: () => {
90
+ const withLock = `{"dialect":"${dialect}","subject":"8","parents":[],"snapshot":"8","generation":0,"lock":{"d":"8"}}`
91
+ assertEq(detectRevision(utf8Bytes(withLock)).mime_type, 'application/vnd.fjs.revision+json')
92
+ assertEq(detectRevision(utf8Bytes(revisionJson)).mime_type, 'application/vnd.fjs.revision+json')
93
+ },
94
+
95
+ // `lockDialect` carries the semantic check too: a structurally valid lock
96
+ // blob whose binding is not a cbase32 hash is not detected as one, exactly
97
+ // as its `decodeText` would say.
98
+ nonHashLockValueFallsThrough: () => {
99
+ const text = `{"dialect":"${lockDialectName}","lock":{"dependency":"not a hash"}}`
100
+ const m = detectRevision(utf8Bytes(text))
101
+ assertEq(m.type, 'text')
102
+ assertEq(m.mime_type, 'text/plain')
103
+ },
104
+
105
+ // The note dialect is registered with no refinement, so structure alone
106
+ // decides the match — a valid note is recognized alongside its siblings.
107
+ validNote: () => {
108
+ const m = detectRevision(utf8Bytes(`{"dialect":"${noteDialectName}","text":"hi"}`))
109
+ assertEq(m.type, 'text')
110
+ assertEq(m.mime_type, 'application/vnd.fjs.note+json')
92
111
  // Same tag, wrong shape: no entry matches.
93
- assertEq(d(utf8Bytes('{"dialect":"vnd.fjs.note","text":42}')).mime_type, 'text/plain')
112
+ assertEq(detectRevision(utf8Bytes(`{"dialect":"${noteDialectName}","text":42}`)).mime_type, 'text/plain')
94
113
  },
95
114
 
96
115
  // The name is neither grammar-checked nor allowlisted: a dialect outside
@@ -17,12 +17,13 @@
17
17
  * @import { Unknown } from '../json/types.ts'
18
18
  * @import { Result } from '../../types/result/types.ts'
19
19
  * @import { DialectEntry } from '../types.ts'
20
- * @import { Revision, RevisionError } from './types.ts'
20
+ * @import { String as RttiString } from '../../types/rtti/types.ts'
21
+ * @import { LockField, LockFieldSchema, LockMap, LockSchema, Revision, RevisionError } from './types.ts'
21
22
  */
22
23
  import type { Unknown } from '../json/types.ts';
23
24
  import type { Result } from '../../types/result/types.ts';
24
25
  import type { DialectEntry } from '../types.ts';
25
- import type { Revision, RevisionError } from './types.ts';
26
+ import type { LockField, LockFieldSchema, LockMap, LockSchema, Revision, RevisionError } from './types.ts';
26
27
  /**
27
28
  * Format tag: names the dialect of this BLOB. The media type it is served
28
29
  * with is derived mechanically: `application/` + `dialect` + `+json`.
@@ -40,8 +41,52 @@ export declare const mediaType: "application/vnd.fjs.revision+json";
40
41
  * not by this schema on its own.
41
42
  */
42
43
  export declare const hash: import("../../types/rtti/types.ts")._Type0<"string">;
43
- /** Structural schema for a Stage 1 flat lock map. */
44
- export declare const _lock: import("../../types/rtti/types.ts").Type1<"record", import("../../types/rtti/types.ts")._Type0<"string">>;
44
+ /**
45
+ * rtti schema for a lock map: an open map whose every value is either a
46
+ * direct hash string or a nested lock map, to any depth.
47
+ *
48
+ * Self-referential through {@link lockValue}, which is a module-level
49
+ * constant rather than a union rebuilt inside the thunk: the rtti data form
50
+ * (`fjs/types/rtti/data`, which `toJsonSchema` routes through) closes
51
+ * reference cycles by *identity*, so a schema handing out a fresh union thunk
52
+ * on every call would present an infinite graph and never terminate.
53
+ *
54
+ * The named `@type` — rather than `@type {const}` — is what a self-referential
55
+ * schema needs twice over: a `const` cannot reference itself in its own
56
+ * initializer at all, and naming the recursive position is also what keeps
57
+ * declaration emit from inlining the structure and giving up at depth (see
58
+ * `fjs/AGENTS.md` §3.2 and `../json/rtti/module.f.mjs`).
59
+ *
60
+ * Like `hash`, this is `string` at the structural level; cbase32 decodability
61
+ * of every direct value, at every depth, is enforced by
62
+ * {@link checkReferences}.
63
+ *
64
+ * @type {LockSchema}
65
+ */
66
+ export declare const lock: LockSchema;
67
+ /**
68
+ * rtti schema for a revision's `lock` **field**: the bindings inline as a lock
69
+ * map, or a hash naming a `vnd.fjs.lock` blob (`fjs/media/lock`) that holds
70
+ * one to share — see [Shared lock references](./README.md#shared-lock-references).
71
+ *
72
+ * Structurally identical to {@link lockValue}, and deliberately a separate
73
+ * name: the two positions mean different things. A string *inside* a map is a
74
+ * dependency's content hash; a string in this position is a lock blob's hash,
75
+ * i.e. where the whole map lives. Only the top level is widened, so a nested
76
+ * string keeps meaning exactly what it always did and no position is
77
+ * ambiguous.
78
+ *
79
+ * Widening the field rather than adding a `lockRef` sibling is what keeps this
80
+ * dialect: an older reader validates `lock` as a map and rejects a string
81
+ * outright, whereas an unknown sibling field would validate and be read as
82
+ * "no bindings were recorded" — the fail-open misread the versioning rule
83
+ * exists to prevent. It also makes "inline map *and* reference" unstatable, so
84
+ * the format defines no precedence between them, consistent with its refusal
85
+ * to define overlay or inheritance for nested maps.
86
+ *
87
+ * @type {LockFieldSchema}
88
+ */
89
+ export declare const lockField: LockFieldSchema;
45
90
  /**
46
91
  * rtti schema for a `revision` BLOB. See the README for the full semantics of
47
92
  * each field; `dialect` is the type discriminant, matched here as an exact
@@ -54,7 +99,7 @@ export declare const revisionSchema: {
54
99
  readonly snapshot: import("../../types/rtti/types.ts")._Type0<"string">;
55
100
  readonly generation: import("../../types/rtti/types.ts")._Type0<"number">;
56
101
  readonly archived: import("../../types/rtti/types.ts").Or<readonly [true, undefined]>;
57
- readonly lock: import("../../types/rtti/types.ts").Or<readonly [import("../../types/rtti/types.ts").Type1<"record", import("../../types/rtti/types.ts")._Type0<"string">>, undefined]>;
102
+ readonly lock: import("../../types/rtti/types.ts").Or<readonly [LockFieldSchema, undefined]>;
58
103
  };
59
104
  /** Serializes a revision canonically, recursively sorting every object's property names.
60
105
  * @type {(revision: Revision) => string}
@@ -64,12 +109,38 @@ export declare const encodeText: (revision: Revision) => string;
64
109
  * @type {(s: string) => boolean}
65
110
  */
66
111
  export declare const isHash: (s: string) => boolean;
112
+ /**
113
+ * The first reason a structurally valid lock map is not a valid one, or `null`
114
+ * — {@link lockError} rooted at the empty scope, so a reported path is
115
+ * relative to the map itself.
116
+ *
117
+ * Exported because `fjs/media/lock` validates the very same map as a
118
+ * standalone blob: one recursive schema and one semantic check, so a map means
119
+ * the same thing inline and shared, and the two forms cannot drift.
120
+ *
121
+ * @type {(lock: LockMap) => string | null}
122
+ */
123
+ export declare const lockMapError: (lock: LockMap) => string | null;
124
+ /**
125
+ * The first reason a structurally valid `lock` field is not a valid one, or
126
+ * `null`. A map is checked entry by entry ({@link lockMapError}); a string is
127
+ * a reference to a `vnd.fjs.lock` blob and is checked as a cbase32 hash and
128
+ * nothing more — this module is pure format with no store access, so whether
129
+ * the blob exists, and what its bindings mean once fetched, stay a resolver's
130
+ * business exactly as they do for `snapshot`.
131
+ *
132
+ * @type {(value: LockField) => string | null}
133
+ */
134
+ export declare const lockFieldError: (value: LockField) => string | null;
67
135
  /**
68
136
  * Checks the semantic refinements the structural schema can't express on an
69
137
  * already shape-valid revision: every `parents` entry and the `snapshot` must
70
- * decode as a cbase32 hash ({@link isHash}), and `generation` must be a
138
+ * decode as a cbase32 hash ({@link isHash}), the `lock` field must too
139
+ * every direct value at every depth of an inline map, or the shared-lock
140
+ * reference itself ({@link lockFieldError}) — and `generation` must be a
71
141
  * non-negative *safe* integer. `subject` is not checked — it is an identity
72
- * string, never a snapshot reference, so any string is valid.
142
+ * string, never a snapshot reference, so any string is valid, and the same
143
+ * goes for a lock map's keys, which are subjects.
73
144
  *
74
145
  * `generation` uses `Number.isSafeInteger`, not `Number.isInteger`: a value at
75
146
  * or above `2 ** 53` passes `isInteger` but is no longer uniquely
@@ -97,6 +168,11 @@ export declare const checkReferences: (r: Revision) => Result<Revision, string>;
97
168
  * Validates an already-parsed JSON value as a `revision` BLOB: structural
98
169
  * (rtti) validation followed by the hash / generation semantic checks.
99
170
  *
171
+ * `RevisionError` is the union of the two stages' own error types, so each
172
+ * failure reaches the caller as it was raised — `ValidationError` from the
173
+ * schema, `string` from {@link checkReferences} — which is exactly what
174
+ * `okThen` produces here.
175
+ *
100
176
  * @type {(value: Unknown) => Result<Revision, RevisionError>}
101
177
  */
102
178
  export declare const validate: (value: Unknown) => Result<Revision, RevisionError>;
@@ -17,14 +17,15 @@
17
17
  * @import { Unknown } from '../json/types.ts'
18
18
  * @import { Result } from '../../types/result/types.ts'
19
19
  * @import { DialectEntry } from '../types.ts'
20
- * @import { Revision, RevisionError } from './types.ts'
20
+ * @import { String as RttiString } from '../../types/rtti/types.ts'
21
+ * @import { LockField, LockFieldSchema, LockMap, LockSchema, Revision, RevisionError } from './types.ts'
21
22
  */
22
23
 
23
- import { array, number, option, record, string } from '../../types/rtti/module.f.mjs'
24
- import { validate as rttiValidate } from '../../types/rtti/validate/module.f.mjs'
24
+ import { array, number, option, string } from '../../types/rtti/module.f.mjs'
25
+ import { parse as rttiParse } from '../../types/rtti/parse/module.f.mjs'
25
26
  import { parse as parseJson } from '../json/module.f.mjs'
26
27
  import { cBase32ToVec } from '../../basen/cbase32/module.f.mjs'
27
- import { error, ok } from '../../types/result/module.f.mjs'
28
+ import { error, ok, okThen } from '../../types/result/module.f.mjs'
28
29
  import { dialectEntry } from '../module.f.mjs'
29
30
  import { definedEntries, sort } from '../../types/object/module.f.mjs'
30
31
  import { stringify } from '../json/module.f.mjs'
@@ -49,8 +50,64 @@ export const mediaType = /** @type {const} */ (`application/${dialect}+json`)
49
50
  */
50
51
  export const hash = string
51
52
 
52
- /** Structural schema for a Stage 1 flat lock map. */
53
- export const _lock = record(string)
53
+ /**
54
+ * rtti schema for a lock map: an open map whose every value is either a
55
+ * direct hash string or a nested lock map, to any depth.
56
+ *
57
+ * Self-referential through {@link lockValue}, which is a module-level
58
+ * constant rather than a union rebuilt inside the thunk: the rtti data form
59
+ * (`fjs/types/rtti/data`, which `toJsonSchema` routes through) closes
60
+ * reference cycles by *identity*, so a schema handing out a fresh union thunk
61
+ * on every call would present an infinite graph and never terminate.
62
+ *
63
+ * The named `@type` — rather than `@type {const}` — is what a self-referential
64
+ * schema needs twice over: a `const` cannot reference itself in its own
65
+ * initializer at all, and naming the recursive position is also what keeps
66
+ * declaration emit from inlining the structure and giving up at depth (see
67
+ * `fjs/AGENTS.md` §3.2 and `../json/rtti/module.f.mjs`).
68
+ *
69
+ * Like `hash`, this is `string` at the structural level; cbase32 decodability
70
+ * of every direct value, at every depth, is enforced by
71
+ * {@link checkReferences}.
72
+ *
73
+ * @type {LockSchema}
74
+ */
75
+ export const lock = () => ['record', lockValue]
76
+
77
+ /**
78
+ * One lock-map value: a direct hash, or a nested lock map. Written as the
79
+ * union tuple rather than as `or(string, lock)` so the thunk carries the name
80
+ * `lockValue`: this is where the reference cycle closes, and the data form
81
+ * names a rule after its defining function — an anonymous thunk would publish
82
+ * the recursion as `$defs: { '': … }` in every derived JSON Schema.
83
+ *
84
+ * @type {() => readonly['or', RttiString, LockSchema]}
85
+ */
86
+ const lockValue = () => ['or', string, lock]
87
+
88
+ /**
89
+ * rtti schema for a revision's `lock` **field**: the bindings inline as a lock
90
+ * map, or a hash naming a `vnd.fjs.lock` blob (`fjs/media/lock`) that holds
91
+ * one to share — see [Shared lock references](./README.md#shared-lock-references).
92
+ *
93
+ * Structurally identical to {@link lockValue}, and deliberately a separate
94
+ * name: the two positions mean different things. A string *inside* a map is a
95
+ * dependency's content hash; a string in this position is a lock blob's hash,
96
+ * i.e. where the whole map lives. Only the top level is widened, so a nested
97
+ * string keeps meaning exactly what it always did and no position is
98
+ * ambiguous.
99
+ *
100
+ * Widening the field rather than adding a `lockRef` sibling is what keeps this
101
+ * dialect: an older reader validates `lock` as a map and rejects a string
102
+ * outright, whereas an unknown sibling field would validate and be read as
103
+ * "no bindings were recorded" — the fail-open misread the versioning rule
104
+ * exists to prevent. It also makes "inline map *and* reference" unstatable, so
105
+ * the format defines no precedence between them, consistent with its refusal
106
+ * to define overlay or inheritance for nested maps.
107
+ *
108
+ * @type {LockFieldSchema}
109
+ */
110
+ export const lockField = () => ['or', hash, lock]
54
111
 
55
112
  /**
56
113
  * rtti schema for a `revision` BLOB. See the README for the full semantics of
@@ -64,7 +121,7 @@ export const revisionSchema = /** @type {const} */ ({
64
121
  snapshot: hash,
65
122
  generation: number,
66
123
  archived: option(true),
67
- lock: option(_lock),
124
+ lock: option(lockField),
68
125
  })
69
126
 
70
127
  /** Serializes a revision canonically, recursively sorting every object's property names.
@@ -73,19 +130,70 @@ export const revisionSchema = /** @type {const} */ ({
73
130
  export const encodeText = stringify(sort)
74
131
 
75
132
  /** Structural-only validator: checks the shape, not the hash / generation semantics. */
76
- const validateShape = rttiValidate(revisionSchema)
133
+ const validateShape = rttiParse(revisionSchema)
77
134
 
78
135
  /** True when `s` decodes as a cbase32 CAS hash (rejects `https://` and any other non-cbase32 string).
79
136
  * @type {(s: string) => boolean}
80
137
  */
81
138
  export const isHash = s => cBase32ToVec(s) !== null
82
139
 
140
+ /**
141
+ * The first reason a structurally valid lock map is not a valid one, or
142
+ * `null` when every direct value at every depth is a cbase32 hash
143
+ * ({@link isHash}). Nested maps are scopes, not references, so only the
144
+ * strings are checked; `scope` names the path walked to reach the offending
145
+ * value, so a failure deep in a nested map still says where it is.
146
+ *
147
+ * @type {(scope: readonly string[]) => (lock: LockMap) => string | null}
148
+ */
149
+ const lockError = scope => lock => {
150
+ for (const [subject, value] of definedEntries(lock)) {
151
+ const path = [...scope, subject]
152
+ const message = typeof value === 'string'
153
+ ? (isHash(value) ? null : `lock value for ${path.join('/')} is not a valid hash: ${value}`)
154
+ : lockError(path)(value)
155
+ if (message !== null) { return message }
156
+ }
157
+ return null
158
+ }
159
+
160
+ /**
161
+ * The first reason a structurally valid lock map is not a valid one, or `null`
162
+ * — {@link lockError} rooted at the empty scope, so a reported path is
163
+ * relative to the map itself.
164
+ *
165
+ * Exported because `fjs/media/lock` validates the very same map as a
166
+ * standalone blob: one recursive schema and one semantic check, so a map means
167
+ * the same thing inline and shared, and the two forms cannot drift.
168
+ *
169
+ * @type {(lock: LockMap) => string | null}
170
+ */
171
+ export const lockMapError = lockError([])
172
+
173
+ /**
174
+ * The first reason a structurally valid `lock` field is not a valid one, or
175
+ * `null`. A map is checked entry by entry ({@link lockMapError}); a string is
176
+ * a reference to a `vnd.fjs.lock` blob and is checked as a cbase32 hash and
177
+ * nothing more — this module is pure format with no store access, so whether
178
+ * the blob exists, and what its bindings mean once fetched, stay a resolver's
179
+ * business exactly as they do for `snapshot`.
180
+ *
181
+ * @type {(value: LockField) => string | null}
182
+ */
183
+ export const lockFieldError = value =>
184
+ typeof value === 'string'
185
+ ? (isHash(value) ? null : `lock reference is not a valid hash: ${value}`)
186
+ : lockMapError(value)
187
+
83
188
  /**
84
189
  * Checks the semantic refinements the structural schema can't express on an
85
190
  * already shape-valid revision: every `parents` entry and the `snapshot` must
86
- * decode as a cbase32 hash ({@link isHash}), and `generation` must be a
191
+ * decode as a cbase32 hash ({@link isHash}), the `lock` field must too
192
+ * every direct value at every depth of an inline map, or the shared-lock
193
+ * reference itself ({@link lockFieldError}) — and `generation` must be a
87
194
  * non-negative *safe* integer. `subject` is not checked — it is an identity
88
- * string, never a snapshot reference, so any string is valid.
195
+ * string, never a snapshot reference, so any string is valid, and the same
196
+ * goes for a lock map's keys, which are subjects.
89
197
  *
90
198
  * `generation` uses `Number.isSafeInteger`, not `Number.isInteger`: a value at
91
199
  * or above `2 ** 53` passes `isInteger` but is no longer uniquely
@@ -113,9 +221,8 @@ export const checkReferences = r => {
113
221
  if (!isHash(p)) { return error(`parent is not a valid hash: ${p}`) }
114
222
  }
115
223
  if (!isHash(r.snapshot)) { return error(`snapshot is not a valid hash: ${r.snapshot}`) }
116
- for (const [subject, snapshot] of definedEntries(r.lock ?? {})) {
117
- if (!isHash(snapshot)) { return error(`lock value for ${subject} is not a valid hash: ${snapshot}`) }
118
- }
224
+ const lockMessage = r.lock === undefined ? null : lockFieldError(r.lock)
225
+ if (lockMessage !== null) { return error(lockMessage) }
119
226
  if (!Number.isSafeInteger(r.generation) || r.generation < 0) {
120
227
  return error(`generation must be a non-negative safe integer: ${r.generation}`)
121
228
  }
@@ -126,13 +233,14 @@ export const checkReferences = r => {
126
233
  * Validates an already-parsed JSON value as a `revision` BLOB: structural
127
234
  * (rtti) validation followed by the hash / generation semantic checks.
128
235
  *
236
+ * `RevisionError` is the union of the two stages' own error types, so each
237
+ * failure reaches the caller as it was raised — `ValidationError` from the
238
+ * schema, `string` from {@link checkReferences} — which is exactly what
239
+ * `okThen` produces here.
240
+ *
129
241
  * @type {(value: Unknown) => Result<Revision, RevisionError>}
130
242
  */
131
- export const validate = value => {
132
- const [t, v] = validateShape(value)
133
- if (t === 'error') { return error(v) }
134
- return checkReferences(v)
135
- }
243
+ export const validate = value => okThen(checkReferences)(validateShape(value))
136
244
 
137
245
  /**
138
246
  * Decodes `text` as a `revision` BLOB: JSON-parses it, then validates it per
@@ -141,11 +249,7 @@ export const validate = value => {
141
249
  *
142
250
  * @type {(text: string) => Result<Revision, RevisionError>}
143
251
  */
144
- export const decodeText = text => {
145
- const [t, v] = parseJson(text)
146
- if (t === 'error') { return error(v) }
147
- return validate(v)
148
- }
252
+ export const decodeText = text => okThen(validate)(parseJson(text))
149
253
 
150
254
  /** {@link checkReferences} as the `boolean` refinement a {@link DialectEntry} takes.
151
255
  * @type {(r: Revision) => boolean}
@@ -1,3 +1,7 @@
1
+ /**
2
+ * @import { Object as JsonObject } from '../json/types.ts'
3
+ * @import { LockMap } from './types.ts'
4
+ */
1
5
  export declare const proof: {
2
6
  dialectAndMediaType: () => void;
3
7
  isHash: {
@@ -24,6 +28,13 @@ export declare const proof: {
24
28
  malformedLockRejected: () => void;
25
29
  invalidHashLockRejected: () => void;
26
30
  aliasHashLockAccepted: () => void;
31
+ nestedLockAccepted: () => void;
32
+ deeplyNestedLockAccepted: () => void;
33
+ malformedNestedLockRejected: () => void;
34
+ invalidNestedHashLockRejected: () => void;
35
+ sharedLockReferenceAccepted: () => void;
36
+ invalidSharedLockReferenceRejected: () => void;
37
+ nestedValueIsStillNotAReference: () => void;
27
38
  wrongDialectRejected: () => void;
28
39
  missingSubjectRejected: () => void;
29
40
  extraFieldsAccepted: () => void;
@@ -36,6 +47,9 @@ export declare const proof: {
36
47
  };
37
48
  encodeText: {
38
49
  recursivelySortsObjectsLexicographically: () => void;
50
+ sortsNestedLockKeys: () => void;
51
+ equivalentNestedLockOrdersConverge: () => void;
52
+ serializesSharedLockReferenceAsAString: () => void;
39
53
  preservesArrayOrder: () => void;
40
54
  parsedEquivalentSourcesConverge: () => void;
41
55
  };