@proposit/proposit-core 0.8.9

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 (429) hide show
  1. package/README.md +1032 -0
  2. package/dist/cli/commands/analysis.d.ts +3 -0
  3. package/dist/cli/commands/analysis.d.ts.map +1 -0
  4. package/dist/cli/commands/analysis.js +504 -0
  5. package/dist/cli/commands/analysis.js.map +1 -0
  6. package/dist/cli/commands/arguments.d.ts +3 -0
  7. package/dist/cli/commands/arguments.d.ts.map +1 -0
  8. package/dist/cli/commands/arguments.js +187 -0
  9. package/dist/cli/commands/arguments.js.map +1 -0
  10. package/dist/cli/commands/claims.d.ts +3 -0
  11. package/dist/cli/commands/claims.d.ts.map +1 -0
  12. package/dist/cli/commands/claims.js +120 -0
  13. package/dist/cli/commands/claims.js.map +1 -0
  14. package/dist/cli/commands/diff.d.ts +3 -0
  15. package/dist/cli/commands/diff.d.ts.map +1 -0
  16. package/dist/cli/commands/diff.js +61 -0
  17. package/dist/cli/commands/diff.js.map +1 -0
  18. package/dist/cli/commands/expressions.d.ts +3 -0
  19. package/dist/cli/commands/expressions.d.ts.map +1 -0
  20. package/dist/cli/commands/expressions.js +344 -0
  21. package/dist/cli/commands/expressions.js.map +1 -0
  22. package/dist/cli/commands/graph.d.ts +13 -0
  23. package/dist/cli/commands/graph.d.ts.map +1 -0
  24. package/dist/cli/commands/graph.js +382 -0
  25. package/dist/cli/commands/graph.js.map +1 -0
  26. package/dist/cli/commands/meta.d.ts +3 -0
  27. package/dist/cli/commands/meta.d.ts.map +1 -0
  28. package/dist/cli/commands/meta.js +14 -0
  29. package/dist/cli/commands/meta.js.map +1 -0
  30. package/dist/cli/commands/parse.d.ts +3 -0
  31. package/dist/cli/commands/parse.d.ts.map +1 -0
  32. package/dist/cli/commands/parse.js +171 -0
  33. package/dist/cli/commands/parse.js.map +1 -0
  34. package/dist/cli/commands/premises.d.ts +3 -0
  35. package/dist/cli/commands/premises.d.ts.map +1 -0
  36. package/dist/cli/commands/premises.js +261 -0
  37. package/dist/cli/commands/premises.js.map +1 -0
  38. package/dist/cli/commands/render.d.ts +3 -0
  39. package/dist/cli/commands/render.d.ts.map +1 -0
  40. package/dist/cli/commands/render.js +109 -0
  41. package/dist/cli/commands/render.js.map +1 -0
  42. package/dist/cli/commands/repair.d.ts +3 -0
  43. package/dist/cli/commands/repair.d.ts.map +1 -0
  44. package/dist/cli/commands/repair.js +53 -0
  45. package/dist/cli/commands/repair.js.map +1 -0
  46. package/dist/cli/commands/roles.d.ts +3 -0
  47. package/dist/cli/commands/roles.d.ts.map +1 -0
  48. package/dist/cli/commands/roles.js +64 -0
  49. package/dist/cli/commands/roles.js.map +1 -0
  50. package/dist/cli/commands/sources.d.ts +3 -0
  51. package/dist/cli/commands/sources.d.ts.map +1 -0
  52. package/dist/cli/commands/sources.js +103 -0
  53. package/dist/cli/commands/sources.js.map +1 -0
  54. package/dist/cli/commands/validate.d.ts +3 -0
  55. package/dist/cli/commands/validate.d.ts.map +1 -0
  56. package/dist/cli/commands/validate.js +27 -0
  57. package/dist/cli/commands/validate.js.map +1 -0
  58. package/dist/cli/commands/variables.d.ts +3 -0
  59. package/dist/cli/commands/variables.d.ts.map +1 -0
  60. package/dist/cli/commands/variables.js +206 -0
  61. package/dist/cli/commands/variables.js.map +1 -0
  62. package/dist/cli/commands/version-show.d.ts +3 -0
  63. package/dist/cli/commands/version-show.d.ts.map +1 -0
  64. package/dist/cli/commands/version-show.js +31 -0
  65. package/dist/cli/commands/version-show.js.map +1 -0
  66. package/dist/cli/config.d.ts +8 -0
  67. package/dist/cli/config.d.ts.map +1 -0
  68. package/dist/cli/config.js +24 -0
  69. package/dist/cli/config.js.map +1 -0
  70. package/dist/cli/engine.d.ts +19 -0
  71. package/dist/cli/engine.d.ts.map +1 -0
  72. package/dist/cli/engine.js +173 -0
  73. package/dist/cli/engine.js.map +1 -0
  74. package/dist/cli/import.d.ts +22 -0
  75. package/dist/cli/import.d.ts.map +1 -0
  76. package/dist/cli/import.js +242 -0
  77. package/dist/cli/import.js.map +1 -0
  78. package/dist/cli/llm/index.d.ts +6 -0
  79. package/dist/cli/llm/index.d.ts.map +1 -0
  80. package/dist/cli/llm/index.js +26 -0
  81. package/dist/cli/llm/index.js.map +1 -0
  82. package/dist/cli/llm/openai.d.ts +4 -0
  83. package/dist/cli/llm/openai.d.ts.map +1 -0
  84. package/dist/cli/llm/openai.js +44 -0
  85. package/dist/cli/llm/openai.js.map +1 -0
  86. package/dist/cli/llm/types.d.ts +14 -0
  87. package/dist/cli/llm/types.d.ts.map +1 -0
  88. package/dist/cli/llm/types.js +2 -0
  89. package/dist/cli/llm/types.js.map +1 -0
  90. package/dist/cli/logging.d.ts +8 -0
  91. package/dist/cli/logging.d.ts.map +1 -0
  92. package/dist/cli/logging.js +23 -0
  93. package/dist/cli/logging.js.map +1 -0
  94. package/dist/cli/output/diff-renderer.d.ts +4 -0
  95. package/dist/cli/output/diff-renderer.d.ts.map +1 -0
  96. package/dist/cli/output/diff-renderer.js +89 -0
  97. package/dist/cli/output/diff-renderer.js.map +1 -0
  98. package/dist/cli/output.d.ts +6 -0
  99. package/dist/cli/output.d.ts.map +1 -0
  100. package/dist/cli/output.js +41 -0
  101. package/dist/cli/output.js.map +1 -0
  102. package/dist/cli/router.d.ts +14 -0
  103. package/dist/cli/router.d.ts.map +1 -0
  104. package/dist/cli/router.js +59 -0
  105. package/dist/cli/router.js.map +1 -0
  106. package/dist/cli/schemata.d.ts +74 -0
  107. package/dist/cli/schemata.d.ts.map +1 -0
  108. package/dist/cli/schemata.js +89 -0
  109. package/dist/cli/schemata.js.map +1 -0
  110. package/dist/cli/storage/analysis.d.ts +9 -0
  111. package/dist/cli/storage/analysis.d.ts.map +1 -0
  112. package/dist/cli/storage/analysis.js +108 -0
  113. package/dist/cli/storage/analysis.js.map +1 -0
  114. package/dist/cli/storage/arguments.d.ts +12 -0
  115. package/dist/cli/storage/arguments.d.ts.map +1 -0
  116. package/dist/cli/storage/arguments.js +80 -0
  117. package/dist/cli/storage/arguments.js.map +1 -0
  118. package/dist/cli/storage/libraries.d.ts +14 -0
  119. package/dist/cli/storage/libraries.d.ts.map +1 -0
  120. package/dist/cli/storage/libraries.js +80 -0
  121. package/dist/cli/storage/libraries.js.map +1 -0
  122. package/dist/cli/storage/premises.d.ts +9 -0
  123. package/dist/cli/storage/premises.d.ts.map +1 -0
  124. package/dist/cli/storage/premises.js +67 -0
  125. package/dist/cli/storage/premises.js.map +1 -0
  126. package/dist/cli/storage/roles.d.ts +4 -0
  127. package/dist/cli/storage/roles.d.ts.map +1 -0
  128. package/dist/cli/storage/roles.js +26 -0
  129. package/dist/cli/storage/roles.js.map +1 -0
  130. package/dist/cli/storage/variables.d.ts +4 -0
  131. package/dist/cli/storage/variables.d.ts.map +1 -0
  132. package/dist/cli/storage/variables.js +36 -0
  133. package/dist/cli/storage/variables.js.map +1 -0
  134. package/dist/cli.d.ts +3 -0
  135. package/dist/cli.d.ts.map +1 -0
  136. package/dist/cli.js +65 -0
  137. package/dist/cli.js.map +1 -0
  138. package/dist/extensions/basics/argument-parser.d.ts +12 -0
  139. package/dist/extensions/basics/argument-parser.d.ts.map +1 -0
  140. package/dist/extensions/basics/argument-parser.js +27 -0
  141. package/dist/extensions/basics/argument-parser.js.map +1 -0
  142. package/dist/extensions/basics/index.d.ts +4 -0
  143. package/dist/extensions/basics/index.d.ts.map +1 -0
  144. package/dist/extensions/basics/index.js +3 -0
  145. package/dist/extensions/basics/index.js.map +1 -0
  146. package/dist/extensions/basics/schemata.d.ts +35 -0
  147. package/dist/extensions/basics/schemata.d.ts.map +1 -0
  148. package/dist/extensions/basics/schemata.js +55 -0
  149. package/dist/extensions/basics/schemata.js.map +1 -0
  150. package/dist/extensions/ieee/formatting.d.ts +18 -0
  151. package/dist/extensions/ieee/formatting.d.ts.map +1 -0
  152. package/dist/extensions/ieee/formatting.js +57 -0
  153. package/dist/extensions/ieee/formatting.js.map +1 -0
  154. package/dist/extensions/ieee/index.d.ts +6 -0
  155. package/dist/extensions/ieee/index.d.ts.map +1 -0
  156. package/dist/extensions/ieee/index.js +6 -0
  157. package/dist/extensions/ieee/index.js.map +1 -0
  158. package/dist/extensions/ieee/references.d.ts +1379 -0
  159. package/dist/extensions/ieee/references.d.ts.map +1 -0
  160. package/dist/extensions/ieee/references.js +929 -0
  161. package/dist/extensions/ieee/references.js.map +1 -0
  162. package/dist/extensions/ieee/relaxed.d.ts +1371 -0
  163. package/dist/extensions/ieee/relaxed.d.ts.map +1 -0
  164. package/dist/extensions/ieee/relaxed.js +160 -0
  165. package/dist/extensions/ieee/relaxed.js.map +1 -0
  166. package/dist/extensions/ieee/segment-builder.d.ts +9 -0
  167. package/dist/extensions/ieee/segment-builder.d.ts.map +1 -0
  168. package/dist/extensions/ieee/segment-builder.js +98 -0
  169. package/dist/extensions/ieee/segment-builder.js.map +1 -0
  170. package/dist/extensions/ieee/segment-templates.d.ts +58 -0
  171. package/dist/extensions/ieee/segment-templates.d.ts.map +1 -0
  172. package/dist/extensions/ieee/segment-templates.js +1618 -0
  173. package/dist/extensions/ieee/segment-templates.js.map +1 -0
  174. package/dist/extensions/ieee/source.d.ts +434 -0
  175. package/dist/extensions/ieee/source.d.ts.map +1 -0
  176. package/dist/extensions/ieee/source.js +12 -0
  177. package/dist/extensions/ieee/source.js.map +1 -0
  178. package/dist/index.d.ts +10 -0
  179. package/dist/index.d.ts.map +1 -0
  180. package/dist/index.js +10 -0
  181. package/dist/index.js.map +1 -0
  182. package/dist/lib/consts.d.ts +21 -0
  183. package/dist/lib/consts.d.ts.map +1 -0
  184. package/dist/lib/consts.js +117 -0
  185. package/dist/lib/consts.js.map +1 -0
  186. package/dist/lib/core/argument-engine.d.ts +181 -0
  187. package/dist/lib/core/argument-engine.d.ts.map +1 -0
  188. package/dist/lib/core/argument-engine.js +1294 -0
  189. package/dist/lib/core/argument-engine.js.map +1 -0
  190. package/dist/lib/core/argument-library.d.ts +84 -0
  191. package/dist/lib/core/argument-library.d.ts.map +1 -0
  192. package/dist/lib/core/argument-library.js +122 -0
  193. package/dist/lib/core/argument-library.js.map +1 -0
  194. package/dist/lib/core/argument-validation.d.ts +74 -0
  195. package/dist/lib/core/argument-validation.d.ts.map +1 -0
  196. package/dist/lib/core/argument-validation.js +315 -0
  197. package/dist/lib/core/argument-validation.js.map +1 -0
  198. package/dist/lib/core/change-collector.d.ts +24 -0
  199. package/dist/lib/core/change-collector.d.ts.map +1 -0
  200. package/dist/lib/core/change-collector.js +63 -0
  201. package/dist/lib/core/change-collector.js.map +1 -0
  202. package/dist/lib/core/checksum.d.ts +15 -0
  203. package/dist/lib/core/checksum.d.ts.map +1 -0
  204. package/dist/lib/core/checksum.js +43 -0
  205. package/dist/lib/core/checksum.js.map +1 -0
  206. package/dist/lib/core/claim-library.d.ts +23 -0
  207. package/dist/lib/core/claim-library.d.ts.map +1 -0
  208. package/dist/lib/core/claim-library.js +21 -0
  209. package/dist/lib/core/claim-library.js.map +1 -0
  210. package/dist/lib/core/claim-source-library.d.ts +32 -0
  211. package/dist/lib/core/claim-source-library.d.ts.map +1 -0
  212. package/dist/lib/core/claim-source-library.js +193 -0
  213. package/dist/lib/core/claim-source-library.js.map +1 -0
  214. package/dist/lib/core/diff.d.ts +20 -0
  215. package/dist/lib/core/diff.d.ts.map +1 -0
  216. package/dist/lib/core/diff.js +260 -0
  217. package/dist/lib/core/diff.js.map +1 -0
  218. package/dist/lib/core/evaluation/argument-evaluation.d.ts +53 -0
  219. package/dist/lib/core/evaluation/argument-evaluation.d.ts.map +1 -0
  220. package/dist/lib/core/evaluation/argument-evaluation.js +535 -0
  221. package/dist/lib/core/evaluation/argument-evaluation.js.map +1 -0
  222. package/dist/lib/core/evaluation/grading.d.ts +28 -0
  223. package/dist/lib/core/evaluation/grading.d.ts.map +1 -0
  224. package/dist/lib/core/evaluation/grading.js +44 -0
  225. package/dist/lib/core/evaluation/grading.js.map +1 -0
  226. package/dist/lib/core/evaluation/kleene.d.ts +12 -0
  227. package/dist/lib/core/evaluation/kleene.d.ts.map +1 -0
  228. package/dist/lib/core/evaluation/kleene.js +29 -0
  229. package/dist/lib/core/evaluation/kleene.js.map +1 -0
  230. package/dist/lib/core/evaluation/validation.d.ts +10 -0
  231. package/dist/lib/core/evaluation/validation.d.ts.map +1 -0
  232. package/dist/lib/core/evaluation/validation.js +28 -0
  233. package/dist/lib/core/evaluation/validation.js.map +1 -0
  234. package/dist/lib/core/expression-manager.d.ts +278 -0
  235. package/dist/lib/core/expression-manager.d.ts.map +1 -0
  236. package/dist/lib/core/expression-manager.js +1622 -0
  237. package/dist/lib/core/expression-manager.js.map +1 -0
  238. package/dist/lib/core/fork-library.d.ts +26 -0
  239. package/dist/lib/core/fork-library.d.ts.map +1 -0
  240. package/dist/lib/core/fork-library.js +71 -0
  241. package/dist/lib/core/fork-library.js.map +1 -0
  242. package/dist/lib/core/fork-namespace.d.ts +32 -0
  243. package/dist/lib/core/fork-namespace.d.ts.map +1 -0
  244. package/dist/lib/core/fork-namespace.js +99 -0
  245. package/dist/lib/core/fork-namespace.js.map +1 -0
  246. package/dist/lib/core/fork.d.ts +30 -0
  247. package/dist/lib/core/fork.d.ts.map +1 -0
  248. package/dist/lib/core/fork.js +125 -0
  249. package/dist/lib/core/fork.js.map +1 -0
  250. package/dist/lib/core/interfaces/argument-engine.interfaces.d.ts +366 -0
  251. package/dist/lib/core/interfaces/argument-engine.interfaces.d.ts.map +1 -0
  252. package/dist/lib/core/interfaces/argument-engine.interfaces.js +2 -0
  253. package/dist/lib/core/interfaces/argument-engine.interfaces.js.map +1 -0
  254. package/dist/lib/core/interfaces/index.d.ts +5 -0
  255. package/dist/lib/core/interfaces/index.d.ts.map +1 -0
  256. package/dist/lib/core/interfaces/index.js +2 -0
  257. package/dist/lib/core/interfaces/index.js.map +1 -0
  258. package/dist/lib/core/interfaces/library.interfaces.d.ts +347 -0
  259. package/dist/lib/core/interfaces/library.interfaces.d.ts.map +1 -0
  260. package/dist/lib/core/interfaces/library.interfaces.js +2 -0
  261. package/dist/lib/core/interfaces/library.interfaces.js.map +1 -0
  262. package/dist/lib/core/interfaces/premise-engine.interfaces.d.ts +401 -0
  263. package/dist/lib/core/interfaces/premise-engine.interfaces.d.ts.map +1 -0
  264. package/dist/lib/core/interfaces/premise-engine.interfaces.js +2 -0
  265. package/dist/lib/core/interfaces/premise-engine.interfaces.js.map +1 -0
  266. package/dist/lib/core/interfaces/shared.interfaces.d.ts +28 -0
  267. package/dist/lib/core/interfaces/shared.interfaces.d.ts.map +1 -0
  268. package/dist/lib/core/interfaces/shared.interfaces.js +2 -0
  269. package/dist/lib/core/interfaces/shared.interfaces.js.map +1 -0
  270. package/dist/lib/core/invariant-violation-error.d.ts +10 -0
  271. package/dist/lib/core/invariant-violation-error.d.ts.map +1 -0
  272. package/dist/lib/core/invariant-violation-error.js +16 -0
  273. package/dist/lib/core/invariant-violation-error.js.map +1 -0
  274. package/dist/lib/core/parser/formula-gen.js +923 -0
  275. package/dist/lib/core/parser/formula.d.ts +24 -0
  276. package/dist/lib/core/parser/formula.d.ts.map +1 -0
  277. package/dist/lib/core/parser/formula.js +8 -0
  278. package/dist/lib/core/parser/formula.js.map +1 -0
  279. package/dist/lib/core/premise-engine.d.ts +122 -0
  280. package/dist/lib/core/premise-engine.d.ts.map +1 -0
  281. package/dist/lib/core/premise-engine.js +1362 -0
  282. package/dist/lib/core/premise-engine.js.map +1 -0
  283. package/dist/lib/core/proposit-core.d.ts +111 -0
  284. package/dist/lib/core/proposit-core.d.ts.map +1 -0
  285. package/dist/lib/core/proposit-core.js +365 -0
  286. package/dist/lib/core/proposit-core.js.map +1 -0
  287. package/dist/lib/core/relationships.d.ts +15 -0
  288. package/dist/lib/core/relationships.d.ts.map +1 -0
  289. package/dist/lib/core/relationships.js +319 -0
  290. package/dist/lib/core/relationships.js.map +1 -0
  291. package/dist/lib/core/source-library.d.ts +23 -0
  292. package/dist/lib/core/source-library.d.ts.map +1 -0
  293. package/dist/lib/core/source-library.js +21 -0
  294. package/dist/lib/core/source-library.js.map +1 -0
  295. package/dist/lib/core/variable-manager.d.ts +68 -0
  296. package/dist/lib/core/variable-manager.d.ts.map +1 -0
  297. package/dist/lib/core/variable-manager.js +200 -0
  298. package/dist/lib/core/variable-manager.js.map +1 -0
  299. package/dist/lib/core/versioned-library.d.ts +52 -0
  300. package/dist/lib/core/versioned-library.d.ts.map +1 -0
  301. package/dist/lib/core/versioned-library.js +192 -0
  302. package/dist/lib/core/versioned-library.js.map +1 -0
  303. package/dist/lib/index.d.ts +54 -0
  304. package/dist/lib/index.d.ts.map +1 -0
  305. package/dist/lib/index.js +39 -0
  306. package/dist/lib/index.js.map +1 -0
  307. package/dist/lib/parsing/argument-parser.d.ts +49 -0
  308. package/dist/lib/parsing/argument-parser.d.ts.map +1 -0
  309. package/dist/lib/parsing/argument-parser.js +403 -0
  310. package/dist/lib/parsing/argument-parser.js.map +1 -0
  311. package/dist/lib/parsing/clamp-max-lengths.d.ts +11 -0
  312. package/dist/lib/parsing/clamp-max-lengths.d.ts.map +1 -0
  313. package/dist/lib/parsing/clamp-max-lengths.js +56 -0
  314. package/dist/lib/parsing/clamp-max-lengths.js.map +1 -0
  315. package/dist/lib/parsing/index.d.ts +7 -0
  316. package/dist/lib/parsing/index.d.ts.map +1 -0
  317. package/dist/lib/parsing/index.js +4 -0
  318. package/dist/lib/parsing/index.js.map +1 -0
  319. package/dist/lib/parsing/prompt-builder.d.ts +11 -0
  320. package/dist/lib/parsing/prompt-builder.d.ts.map +1 -0
  321. package/dist/lib/parsing/prompt-builder.js +229 -0
  322. package/dist/lib/parsing/prompt-builder.js.map +1 -0
  323. package/dist/lib/parsing/schemata.d.ts +79 -0
  324. package/dist/lib/parsing/schemata.d.ts.map +1 -0
  325. package/dist/lib/parsing/schemata.js +92 -0
  326. package/dist/lib/parsing/schemata.js.map +1 -0
  327. package/dist/lib/parsing/types.d.ts +24 -0
  328. package/dist/lib/parsing/types.d.ts.map +1 -0
  329. package/dist/lib/parsing/types.js +2 -0
  330. package/dist/lib/parsing/types.js.map +1 -0
  331. package/dist/lib/schemata/analysis.d.ts +9 -0
  332. package/dist/lib/schemata/analysis.d.ts.map +1 -0
  333. package/dist/lib/schemata/analysis.js +13 -0
  334. package/dist/lib/schemata/analysis.js.map +1 -0
  335. package/dist/lib/schemata/argument.d.ts +14 -0
  336. package/dist/lib/schemata/argument.d.ts.map +1 -0
  337. package/dist/lib/schemata/argument.js +24 -0
  338. package/dist/lib/schemata/argument.js.map +1 -0
  339. package/dist/lib/schemata/claim.d.ts +9 -0
  340. package/dist/lib/schemata/claim.d.ts.map +1 -0
  341. package/dist/lib/schemata/claim.js +18 -0
  342. package/dist/lib/schemata/claim.js.map +1 -0
  343. package/dist/lib/schemata/fork.d.ts +76 -0
  344. package/dist/lib/schemata/fork.d.ts.map +1 -0
  345. package/dist/lib/schemata/fork.js +55 -0
  346. package/dist/lib/schemata/fork.js.map +1 -0
  347. package/dist/lib/schemata/import.d.ts +33 -0
  348. package/dist/lib/schemata/import.d.ts.map +1 -0
  349. package/dist/lib/schemata/import.js +18 -0
  350. package/dist/lib/schemata/import.js.map +1 -0
  351. package/dist/lib/schemata/index.d.ts +8 -0
  352. package/dist/lib/schemata/index.d.ts.map +1 -0
  353. package/dist/lib/schemata/index.js +8 -0
  354. package/dist/lib/schemata/index.js.map +1 -0
  355. package/dist/lib/schemata/propositional.d.ts +142 -0
  356. package/dist/lib/schemata/propositional.d.ts.map +1 -0
  357. package/dist/lib/schemata/propositional.js +120 -0
  358. package/dist/lib/schemata/propositional.js.map +1 -0
  359. package/dist/lib/schemata/shared.d.ts +41 -0
  360. package/dist/lib/schemata/shared.d.ts.map +1 -0
  361. package/dist/lib/schemata/shared.js +66 -0
  362. package/dist/lib/schemata/shared.js.map +1 -0
  363. package/dist/lib/schemata/source.d.ts +18 -0
  364. package/dist/lib/schemata/source.d.ts.map +1 -0
  365. package/dist/lib/schemata/source.js +35 -0
  366. package/dist/lib/schemata/source.js.map +1 -0
  367. package/dist/lib/types/checksum.d.ts +20 -0
  368. package/dist/lib/types/checksum.d.ts.map +1 -0
  369. package/dist/lib/types/checksum.js +2 -0
  370. package/dist/lib/types/checksum.js.map +1 -0
  371. package/dist/lib/types/diff.d.ts +60 -0
  372. package/dist/lib/types/diff.d.ts.map +1 -0
  373. package/dist/lib/types/diff.js +2 -0
  374. package/dist/lib/types/diff.js.map +1 -0
  375. package/dist/lib/types/evaluation.d.ts +164 -0
  376. package/dist/lib/types/evaluation.d.ts.map +1 -0
  377. package/dist/lib/types/evaluation.js +2 -0
  378. package/dist/lib/types/evaluation.js.map +1 -0
  379. package/dist/lib/types/fork.d.ts +25 -0
  380. package/dist/lib/types/fork.d.ts.map +1 -0
  381. package/dist/lib/types/fork.js +2 -0
  382. package/dist/lib/types/fork.js.map +1 -0
  383. package/dist/lib/types/grammar.d.ts +38 -0
  384. package/dist/lib/types/grammar.d.ts.map +1 -0
  385. package/dist/lib/types/grammar.js +11 -0
  386. package/dist/lib/types/grammar.js.map +1 -0
  387. package/dist/lib/types/mutation.d.ts +31 -0
  388. package/dist/lib/types/mutation.d.ts.map +1 -0
  389. package/dist/lib/types/mutation.js +2 -0
  390. package/dist/lib/types/mutation.js.map +1 -0
  391. package/dist/lib/types/reactive.d.ts +14 -0
  392. package/dist/lib/types/reactive.d.ts.map +1 -0
  393. package/dist/lib/types/reactive.js +2 -0
  394. package/dist/lib/types/reactive.js.map +1 -0
  395. package/dist/lib/types/relationships.d.ts +36 -0
  396. package/dist/lib/types/relationships.d.ts.map +1 -0
  397. package/dist/lib/types/relationships.js +2 -0
  398. package/dist/lib/types/relationships.js.map +1 -0
  399. package/dist/lib/types/validation.d.ts +47 -0
  400. package/dist/lib/types/validation.d.ts.map +1 -0
  401. package/dist/lib/types/validation.js +43 -0
  402. package/dist/lib/types/validation.js.map +1 -0
  403. package/dist/lib/utils/changeset.d.ts +124 -0
  404. package/dist/lib/utils/changeset.d.ts.map +1 -0
  405. package/dist/lib/utils/changeset.js +221 -0
  406. package/dist/lib/utils/changeset.js.map +1 -0
  407. package/dist/lib/utils/collections.d.ts +12 -0
  408. package/dist/lib/utils/collections.d.ts.map +1 -0
  409. package/dist/lib/utils/collections.js +24 -0
  410. package/dist/lib/utils/collections.js.map +1 -0
  411. package/dist/lib/utils/default-map.d.ts +17 -0
  412. package/dist/lib/utils/default-map.d.ts.map +1 -0
  413. package/dist/lib/utils/default-map.js +33 -0
  414. package/dist/lib/utils/default-map.js.map +1 -0
  415. package/dist/lib/utils/lookup.d.ts +47 -0
  416. package/dist/lib/utils/lookup.d.ts.map +1 -0
  417. package/dist/lib/utils/lookup.js +62 -0
  418. package/dist/lib/utils/lookup.js.map +1 -0
  419. package/dist/lib/utils/position.d.ts +12 -0
  420. package/dist/lib/utils/position.d.ts.map +1 -0
  421. package/dist/lib/utils/position.js +13 -0
  422. package/dist/lib/utils/position.js.map +1 -0
  423. package/package.json +82 -0
  424. package/skills/proposit-core/SKILL.md +35 -0
  425. package/skills/proposit-core/docs/api-usage.md +442 -0
  426. package/skills/proposit-core/docs/architecture.md +256 -0
  427. package/skills/proposit-core/docs/cli.md +304 -0
  428. package/skills/proposit-core/docs/testing.md +281 -0
  429. package/skills/proposit-core/docs/types-schemas.md +648 -0
@@ -0,0 +1,1362 @@
1
+ import { CorePremiseSchema, isExternallyBound, isPremiseBound, } from "../schemata/index.js";
2
+ import { DefaultMap } from "../utils/default-map.js";
3
+ import { midpoint, POSITION_INITIAL, POSITION_MAX } from "../utils/position.js";
4
+ import { sortedCopyById, sortedUnique } from "../utils/collections.js";
5
+ import { kleeneAnd, kleeneIff, kleeneImplies, kleeneNot, kleeneOr, } from "./evaluation/kleene.js";
6
+ import { buildDirectionalVacuity, makeErrorIssue, makeValidationResult, } from "./evaluation/validation.js";
7
+ import { Value } from "typebox/value";
8
+ import { PREMISE_SCHEMA_INVALID, PREMISE_ROOT_EXPRESSION_INVALID, PREMISE_VARIABLE_REF_NOT_FOUND, } from "../types/validation.js";
9
+ import { defaultGenerateId, } from "./argument-engine.js";
10
+ import { DEFAULT_CHECKSUM_CONFIG, normalizeChecksumConfig, serializeChecksumConfig, } from "../consts.js";
11
+ import { ChangeCollector } from "./change-collector.js";
12
+ import { computeHash, entityChecksum } from "./checksum.js";
13
+ import { InvariantViolationError } from "./invariant-violation-error.js";
14
+ import { ExpressionManager } from "./expression-manager.js";
15
+ import { VariableManager } from "./variable-manager.js";
16
+ export class PremiseEngine {
17
+ premise;
18
+ rootExpressionId;
19
+ variables;
20
+ expressions;
21
+ expressionsByVariableId;
22
+ argument;
23
+ checksumConfig;
24
+ checksumDirty = true;
25
+ cachedMetaChecksum;
26
+ cachedDescendantChecksum;
27
+ cachedCombinedChecksum;
28
+ expressionIndex;
29
+ generateId;
30
+ onMutate;
31
+ circularityCheck;
32
+ emptyBoundPremiseCheck;
33
+ variableIdsCallback;
34
+ argumentValidateCallback;
35
+ insideValidation = false;
36
+ constructor(premise, deps, config) {
37
+ this.premise = { ...premise };
38
+ this.argument = deps.argument;
39
+ this.checksumConfig = config?.checksumConfig;
40
+ this.rootExpressionId = undefined;
41
+ this.variables = deps.variables;
42
+ this.expressions = new ExpressionManager(config);
43
+ this.expressionsByVariableId = new DefaultMap(() => new Set());
44
+ this.expressionIndex = deps.expressionIndex;
45
+ this.generateId = config?.generateId ?? defaultGenerateId;
46
+ }
47
+ setOnMutate(callback) {
48
+ this.onMutate = callback;
49
+ }
50
+ setCircularityCheck(check) {
51
+ this.circularityCheck = check;
52
+ }
53
+ setEmptyBoundPremiseCheck(check) {
54
+ this.emptyBoundPremiseCheck = check;
55
+ }
56
+ setVariableIdsCallback(callback) {
57
+ this.variableIdsCallback = callback;
58
+ }
59
+ setArgumentValidateCallback(callback) {
60
+ this.argumentValidateCallback = callback;
61
+ }
62
+ premiseSnapshot() {
63
+ const expressionIndexEntries = [];
64
+ if (this.expressionIndex) {
65
+ for (const [exprId, premiseId] of this.expressionIndex) {
66
+ if (premiseId === this.premise.id) {
67
+ expressionIndexEntries.push([exprId, premiseId]);
68
+ }
69
+ }
70
+ }
71
+ return {
72
+ premiseData: { ...this.premise },
73
+ rootExpressionId: this.rootExpressionId,
74
+ expressionSnapshot: this.expressions.snapshot(),
75
+ expressionIndexEntries,
76
+ };
77
+ }
78
+ restoreFromPremiseSnapshot(snap) {
79
+ this.premise = snap.premiseData;
80
+ this.rootExpressionId = snap.rootExpressionId;
81
+ this.expressions = ExpressionManager.fromSnapshot(snap.expressionSnapshot);
82
+ // Restore expression index entries
83
+ if (this.expressionIndex) {
84
+ for (const [exprId, premiseId] of [...this.expressionIndex]) {
85
+ if (premiseId === this.premise.id) {
86
+ this.expressionIndex.delete(exprId);
87
+ }
88
+ }
89
+ for (const [exprId, premiseId] of snap.expressionIndexEntries) {
90
+ this.expressionIndex.set(exprId, premiseId);
91
+ }
92
+ }
93
+ this.rebuildVariableIndex();
94
+ }
95
+ withValidation(fn) {
96
+ if (this.insideValidation) {
97
+ return fn();
98
+ }
99
+ const snap = this.premiseSnapshot();
100
+ this.insideValidation = true;
101
+ try {
102
+ const result = fn();
103
+ const validation = this.argumentValidateCallback?.() ?? this.validate();
104
+ if (!validation.ok) {
105
+ this.restoreFromPremiseSnapshot(snap);
106
+ throw new InvariantViolationError(validation.violations);
107
+ }
108
+ return result;
109
+ }
110
+ catch (e) {
111
+ if (!(e instanceof InvariantViolationError)) {
112
+ this.restoreFromPremiseSnapshot(snap);
113
+ }
114
+ throw e;
115
+ }
116
+ finally {
117
+ this.insideValidation = false;
118
+ }
119
+ }
120
+ deleteExpressionsUsingVariable(variableId) {
121
+ return this.withValidation(() => {
122
+ const expressionIds = this.expressionsByVariableId.get(variableId);
123
+ if (expressionIds.size === 0) {
124
+ return { result: [], changes: {} };
125
+ }
126
+ const collector = new ChangeCollector();
127
+ // Suppress onMutate during the loop to avoid redundant notifications
128
+ const savedOnMutate = this.onMutate;
129
+ this.onMutate = undefined;
130
+ try {
131
+ // Copy the set since removeExpression mutates expressionsByVariableId
132
+ const removed = [];
133
+ for (const exprId of [...expressionIds]) {
134
+ // The expression may already have been removed as part of a
135
+ // prior subtree deletion or operator collapse in this loop.
136
+ if (!this.expressions.getExpression(exprId))
137
+ continue;
138
+ const { result, changes } = this.removeExpression(exprId, true);
139
+ if (result)
140
+ removed.push(result);
141
+ if (changes.expressions) {
142
+ for (const e of changes.expressions.removed) {
143
+ collector.removedExpression(e);
144
+ }
145
+ }
146
+ }
147
+ // Expressions in the collector already have checksums attached
148
+ // (from ExpressionManager which stores expressions with checksums).
149
+ const changes = collector.toChangeset();
150
+ this.syncExpressionIndex(changes);
151
+ // Restore and fire once if something was removed
152
+ this.onMutate = savedOnMutate;
153
+ if (removed.length > 0) {
154
+ this.onMutate?.();
155
+ }
156
+ return {
157
+ result: removed,
158
+ changes,
159
+ };
160
+ }
161
+ catch (e) {
162
+ this.onMutate = savedOnMutate;
163
+ throw e;
164
+ }
165
+ });
166
+ }
167
+ addExpression(expression) {
168
+ return this.withValidation(() => {
169
+ this.assertBelongsToArgument(expression.argumentId, expression.argumentVersion);
170
+ this.assertVariableExpressionValid(expression);
171
+ if (expression.parentId === null) {
172
+ if (this.rootExpressionId !== undefined) {
173
+ throw new Error(`Premise "${this.premise.id}" already has a root expression.`);
174
+ }
175
+ }
176
+ else {
177
+ if (!this.expressions.getExpression(expression.parentId)) {
178
+ throw new Error(`Parent expression "${expression.parentId}" does not exist in this premise.`);
179
+ }
180
+ }
181
+ const collector = new ChangeCollector();
182
+ this.expressions.setCollector(collector);
183
+ try {
184
+ // Delegate structural validation (operator type checks, position
185
+ // uniqueness, child limits) to ExpressionManager.
186
+ this.expressions.addExpression(expression);
187
+ if (expression.parentId === null) {
188
+ this.rootExpressionId = expression.id;
189
+ }
190
+ if (expression.type === "variable") {
191
+ this.expressionsByVariableId
192
+ .get(expression.variableId)
193
+ .add(expression.id);
194
+ }
195
+ const changes = this.finalizeExpressionMutation(collector);
196
+ return {
197
+ result: this.expressions.getExpression(expression.id),
198
+ changes,
199
+ };
200
+ }
201
+ finally {
202
+ this.expressions.setCollector(null);
203
+ }
204
+ });
205
+ }
206
+ appendExpression(parentId, expression) {
207
+ return this.withValidation(() => {
208
+ this.assertBelongsToArgument(expression.argumentId, expression.argumentVersion);
209
+ this.assertVariableExpressionValid(expression);
210
+ if (parentId === null) {
211
+ if (this.rootExpressionId !== undefined) {
212
+ throw new Error(`Premise "${this.premise.id}" already has a root expression.`);
213
+ }
214
+ }
215
+ else {
216
+ if (!this.expressions.getExpression(parentId)) {
217
+ throw new Error(`Parent expression "${parentId}" does not exist in this premise.`);
218
+ }
219
+ }
220
+ const collector = new ChangeCollector();
221
+ this.expressions.setCollector(collector);
222
+ try {
223
+ this.expressions.appendExpression(parentId, expression);
224
+ if (expression.type === "variable") {
225
+ this.expressionsByVariableId
226
+ .get(expression.variableId)
227
+ .add(expression.id);
228
+ }
229
+ const changes = this.finalizeExpressionMutation(collector);
230
+ return {
231
+ result: this.expressions.getExpression(expression.id),
232
+ changes,
233
+ };
234
+ }
235
+ finally {
236
+ this.expressions.setCollector(null);
237
+ }
238
+ });
239
+ }
240
+ addExpressionRelative(siblingId, relativePosition, expression) {
241
+ return this.withValidation(() => {
242
+ this.assertBelongsToArgument(expression.argumentId, expression.argumentVersion);
243
+ this.assertVariableExpressionValid(expression);
244
+ if (!this.expressions.getExpression(siblingId)) {
245
+ throw new Error(`Expression "${siblingId}" not found in this premise.`);
246
+ }
247
+ const collector = new ChangeCollector();
248
+ this.expressions.setCollector(collector);
249
+ try {
250
+ this.expressions.addExpressionRelative(siblingId, relativePosition, expression);
251
+ if (expression.type === "variable") {
252
+ this.expressionsByVariableId
253
+ .get(expression.variableId)
254
+ .add(expression.id);
255
+ }
256
+ const changes = this.finalizeExpressionMutation(collector);
257
+ return {
258
+ result: this.expressions.getExpression(expression.id),
259
+ changes,
260
+ };
261
+ }
262
+ finally {
263
+ this.expressions.setCollector(null);
264
+ }
265
+ });
266
+ }
267
+ updateExpression(expressionId, updates) {
268
+ return this.withValidation(() => {
269
+ const existing = this.expressions.getExpression(expressionId);
270
+ if (!existing) {
271
+ throw new Error(`Expression "${expressionId}" not found in premise "${this.premise.id}".`);
272
+ }
273
+ if (updates.variableId !== undefined) {
274
+ if (!this.variables.hasVariable(updates.variableId)) {
275
+ throw new Error(`Variable expression "${expressionId}" references non-existent variable "${updates.variableId}".`);
276
+ }
277
+ }
278
+ const collector = new ChangeCollector();
279
+ this.expressions.setCollector(collector);
280
+ try {
281
+ const oldVariableId = existing.type === "variable"
282
+ ? existing.variableId
283
+ : undefined;
284
+ const updated = this.expressions.updateExpression(expressionId, updates);
285
+ if (updates.variableId !== undefined &&
286
+ oldVariableId !== undefined &&
287
+ oldVariableId !== updates.variableId) {
288
+ this.expressionsByVariableId
289
+ .get(oldVariableId)
290
+ ?.delete(expressionId);
291
+ this.expressionsByVariableId
292
+ .get(updates.variableId)
293
+ .add(expressionId);
294
+ }
295
+ const changeset = this.flushAndBuildChangeset(collector);
296
+ if (changeset.expressions !== undefined) {
297
+ this.markDirty();
298
+ this.onMutate?.();
299
+ }
300
+ this.syncExpressionIndex(changeset);
301
+ return {
302
+ result: updated,
303
+ changes: changeset,
304
+ };
305
+ }
306
+ finally {
307
+ this.expressions.setCollector(null);
308
+ }
309
+ });
310
+ }
311
+ removeExpression(expressionId, deleteSubtree) {
312
+ return this.withValidation(() => {
313
+ // Snapshot the expression before removal (for result).
314
+ const snapshot = this.expressions.getExpression(expressionId);
315
+ const collector = new ChangeCollector();
316
+ this.expressions.setCollector(collector);
317
+ try {
318
+ if (!snapshot) {
319
+ return {
320
+ result: undefined,
321
+ changes: collector.toChangeset(),
322
+ };
323
+ }
324
+ if (deleteSubtree) {
325
+ // Snapshot the subtree before deletion so we can clean up
326
+ // expressionsByVariableId for cascade-deleted descendants — they are
327
+ // not individually surfaced by ExpressionManager.removeExpression.
328
+ const subtree = this.collectSubtree(expressionId);
329
+ this.expressions.removeExpression(expressionId, true);
330
+ for (const expr of subtree) {
331
+ if (expr.type === "variable") {
332
+ this.expressionsByVariableId
333
+ .get(expr.variableId)
334
+ ?.delete(expr.id);
335
+ }
336
+ }
337
+ }
338
+ else {
339
+ // Only clean up expressionsByVariableId for the removed
340
+ // expression itself — children survive promotion.
341
+ if (snapshot.type === "variable") {
342
+ this.expressionsByVariableId
343
+ .get(snapshot.variableId)
344
+ ?.delete(snapshot.id);
345
+ }
346
+ this.expressions.removeExpression(expressionId, false);
347
+ }
348
+ const changes = this.finalizeExpressionMutation(collector);
349
+ return {
350
+ result: snapshot,
351
+ changes,
352
+ };
353
+ }
354
+ finally {
355
+ this.expressions.setCollector(null);
356
+ }
357
+ });
358
+ }
359
+ insertExpression(expression, leftNodeId, rightNodeId) {
360
+ return this.withValidation(() => {
361
+ this.assertBelongsToArgument(expression.argumentId, expression.argumentVersion);
362
+ this.assertVariableExpressionValid(expression);
363
+ const collector = new ChangeCollector();
364
+ this.expressions.setCollector(collector);
365
+ try {
366
+ this.expressions.insertExpression(expression, leftNodeId, rightNodeId);
367
+ if (expression.type === "variable") {
368
+ this.expressionsByVariableId
369
+ .get(expression.variableId)
370
+ .add(expression.id);
371
+ }
372
+ const changes = this.finalizeExpressionMutation(collector);
373
+ return {
374
+ result: this.expressions.getExpression(expression.id),
375
+ changes,
376
+ };
377
+ }
378
+ finally {
379
+ this.expressions.setCollector(null);
380
+ }
381
+ });
382
+ }
383
+ wrapExpression(operator, newSibling, leftNodeId, rightNodeId) {
384
+ return this.withValidation(() => {
385
+ this.assertBelongsToArgument(operator.argumentId, operator.argumentVersion);
386
+ this.assertBelongsToArgument(newSibling.argumentId, newSibling.argumentVersion);
387
+ this.assertVariableExpressionValid(newSibling);
388
+ const collector = new ChangeCollector();
389
+ this.expressions.setCollector(collector);
390
+ try {
391
+ this.expressions.wrapExpression(operator, newSibling, leftNodeId, rightNodeId);
392
+ if (newSibling.type === "variable") {
393
+ this.expressionsByVariableId
394
+ .get(newSibling.variableId)
395
+ .add(newSibling.id);
396
+ }
397
+ const changes = this.finalizeExpressionMutation(collector);
398
+ return {
399
+ result: this.expressions.getExpression(operator.id),
400
+ changes,
401
+ };
402
+ }
403
+ finally {
404
+ this.expressions.setCollector(null);
405
+ }
406
+ });
407
+ }
408
+ /**
409
+ * Performs a full normalization sweep on this premise's expression tree.
410
+ * Collapses unjustified formulas, operators with 0/1 children, and inserts
411
+ * formula buffers where needed. Works regardless of `autoNormalize` setting.
412
+ */
413
+ normalizeExpressions() {
414
+ return this.withValidation(() => {
415
+ const collector = new ChangeCollector();
416
+ this.expressions.setCollector(collector);
417
+ try {
418
+ this.expressions.normalize();
419
+ const changes = this.finalizeExpressionMutation(collector);
420
+ return { result: undefined, changes };
421
+ }
422
+ finally {
423
+ this.expressions.setCollector(null);
424
+ }
425
+ });
426
+ }
427
+ toggleNegation(expressionId, extraFields) {
428
+ return this.withValidation(() => {
429
+ const target = this.expressions.getExpression(expressionId);
430
+ if (!target) {
431
+ throw new Error(`Expression "${expressionId}" not found in this premise.`);
432
+ }
433
+ this.assertBelongsToArgument(target.argumentId, target.argumentVersion);
434
+ const collector = new ChangeCollector();
435
+ this.expressions.setCollector(collector);
436
+ try {
437
+ const parent = target.parentId
438
+ ? this.expressions.getExpression(target.parentId)
439
+ : undefined;
440
+ // Check for direct not parent: not(target)
441
+ const isDirectNot = parent?.type === "operator" && parent.operator === "not";
442
+ // Check for formula-buffered not: not(formula(target))
443
+ const grandparent = parent?.type === "formula" && parent.parentId
444
+ ? this.expressions.getExpression(parent.parentId)
445
+ : undefined;
446
+ const isBufferedNot = parent?.type === "formula" &&
447
+ grandparent?.type === "operator" &&
448
+ grandparent.operator === "not";
449
+ if (isDirectNot || isBufferedNot) {
450
+ if (isBufferedNot) {
451
+ // Structure is not → formula → target.
452
+ // Remove just the not (promotes formula into its slot).
453
+ // The formula remains as a transparent wrapper.
454
+ this.expressions.removeExpression(grandparent.id, false);
455
+ }
456
+ else {
457
+ // Remove the NOT operator, promoting target into its slot
458
+ this.expressions.removeExpression(parent.id, false);
459
+ }
460
+ const changes = this.finalizeExpressionMutation(collector);
461
+ return { result: null, changes };
462
+ }
463
+ else {
464
+ // When the target is a non-not operator, insert a formula
465
+ // buffer between the new not and the target so the tree
466
+ // satisfies the operator nesting restriction.
467
+ const needsFormula = target.type === "operator" && target.operator !== "not";
468
+ let notExprId;
469
+ if (needsFormula) {
470
+ // Build not → formula → target
471
+ const formulaExpr = {
472
+ ...extraFields,
473
+ id: this.generateId(),
474
+ argumentId: target.argumentId,
475
+ argumentVersion: target.argumentVersion,
476
+ premiseId: target.premiseId,
477
+ type: "formula",
478
+ parentId: target.parentId,
479
+ position: target.position,
480
+ };
481
+ this.expressions.insertExpression(formulaExpr, expressionId);
482
+ const notExpr = {
483
+ ...extraFields,
484
+ id: this.generateId(),
485
+ argumentId: target.argumentId,
486
+ argumentVersion: target.argumentVersion,
487
+ premiseId: target.premiseId,
488
+ type: "operator",
489
+ operator: "not",
490
+ parentId: target.parentId,
491
+ position: target.position,
492
+ };
493
+ this.expressions.insertExpression(notExpr, formulaExpr.id);
494
+ notExprId = notExpr.id;
495
+ }
496
+ else {
497
+ // Wrap target with a new NOT operator
498
+ const notExpr = {
499
+ ...extraFields,
500
+ id: this.generateId(),
501
+ argumentId: target.argumentId,
502
+ argumentVersion: target.argumentVersion,
503
+ premiseId: target.premiseId,
504
+ type: "operator",
505
+ operator: "not",
506
+ parentId: target.parentId,
507
+ position: target.position,
508
+ };
509
+ this.expressions.insertExpression(notExpr, expressionId);
510
+ notExprId = notExpr.id;
511
+ }
512
+ const changes = this.finalizeExpressionMutation(collector);
513
+ return {
514
+ result: this.expressions.getExpression(notExprId),
515
+ changes,
516
+ };
517
+ }
518
+ }
519
+ finally {
520
+ this.expressions.setCollector(null);
521
+ }
522
+ });
523
+ }
524
+ changeOperator(expressionId, newOperator, sourceChildId, targetChildId, extraFields) {
525
+ return this.withValidation(() => {
526
+ const target = this.expressions.getExpression(expressionId);
527
+ if (!target) {
528
+ throw new Error(`Expression "${expressionId}" not found in this premise.`);
529
+ }
530
+ if (target.type !== "operator") {
531
+ throw new Error(`Expression "${expressionId}" is not an operator expression (type: "${target.type}").`);
532
+ }
533
+ if (target.type === "operator" && target.operator === "not") {
534
+ throw new Error(`Cannot change a "not" operator. Use toggleNegation instead.`);
535
+ }
536
+ this.assertBelongsToArgument(target.argumentId, target.argumentVersion);
537
+ // No-op: already the requested operator
538
+ if (target.type === "operator" && target.operator === newOperator) {
539
+ return { result: target, changes: {} };
540
+ }
541
+ const children = this.expressions.getChildExpressions(expressionId);
542
+ const childCount = children.length;
543
+ const collector = new ChangeCollector();
544
+ this.expressions.setCollector(collector);
545
+ try {
546
+ if (childCount <= 2) {
547
+ // Check for merge condition: parent is same type as newOperator.
548
+ // Only merge when childCount < 2 (degenerate operator). With
549
+ // exactly 2 children the operator is well-formed — just change
550
+ // the type in place.
551
+ const parent = target.parentId
552
+ ? this.expressions.getExpression(target.parentId)
553
+ : undefined;
554
+ let mergeTarget;
555
+ if (childCount < 2) {
556
+ // Look through formula buffer: if parent is formula, check grandparent
557
+ if (parent?.type === "formula" && parent.parentId) {
558
+ const grandparent = this.expressions.getExpression(parent.parentId);
559
+ if (grandparent?.type === "operator" &&
560
+ grandparent.operator === newOperator) {
561
+ mergeTarget = grandparent;
562
+ }
563
+ }
564
+ else if (parent?.type === "operator" &&
565
+ parent.operator === newOperator) {
566
+ mergeTarget = parent;
567
+ }
568
+ }
569
+ if (mergeTarget) {
570
+ // --- MERGE ---
571
+ // Reparent children of the dissolving operator under the merge target.
572
+ // Use the dissolving operator's position slot for the first child,
573
+ // compute midpoint positions for subsequent children.
574
+ // If parent was a formula buffer, we'll dissolve that too
575
+ const formulaToDissolve = parent?.type === "formula" ? parent : undefined;
576
+ // The position slot we're replacing
577
+ const slotPosition = formulaToDissolve
578
+ ? formulaToDissolve.position
579
+ : target.position;
580
+ // Get the merge target's existing children sorted by position to find neighbors
581
+ const mergeChildren = this.expressions.getChildExpressions(mergeTarget.id);
582
+ // Find the position of the next sibling after the slot
583
+ const slotIndex = mergeChildren.findIndex((c) => c.id === (formulaToDissolve?.id ?? expressionId));
584
+ const nextSibling = mergeChildren[slotIndex + 1];
585
+ const nextPosition = nextSibling
586
+ ? nextSibling.position
587
+ : POSITION_MAX;
588
+ // Reparent each child
589
+ for (let i = 0; i < children.length; i++) {
590
+ const childPosition = i === 0
591
+ ? slotPosition
592
+ : midpoint(i === 1
593
+ ? slotPosition
594
+ : children[i - 1].position, nextPosition);
595
+ this.expressions.reparentExpression(children[i].id, mergeTarget.id, childPosition);
596
+ }
597
+ // Delete the dissolving operator (now has no children)
598
+ this.expressions.deleteExpression(expressionId);
599
+ // Delete the formula buffer if it existed (now has no children)
600
+ if (formulaToDissolve) {
601
+ this.expressions.deleteExpression(formulaToDissolve.id);
602
+ }
603
+ const changes = this.finalizeExpressionMutation(collector);
604
+ return { result: null, changes };
605
+ }
606
+ else {
607
+ // --- SIMPLE CHANGE ---
608
+ this.expressions.changeOperatorType(expressionId, newOperator);
609
+ const changes = this.finalizeExpressionMutation(collector);
610
+ return {
611
+ result: this.expressions.getExpression(expressionId),
612
+ changes,
613
+ };
614
+ }
615
+ }
616
+ else {
617
+ // --- SPLIT (>2 children) ---
618
+ if (!sourceChildId || !targetChildId) {
619
+ throw new Error(`Operator "${expressionId}" has ${childCount} children — sourceChildId and targetChildId are required for split.`);
620
+ }
621
+ // Validate source and target are children of the operator
622
+ const sourceChild = this.expressions.getExpression(sourceChildId);
623
+ const targetChild = this.expressions.getExpression(targetChildId);
624
+ if (!sourceChild || sourceChild.parentId !== expressionId) {
625
+ throw new Error(`Expression "${sourceChildId}" is not a child of operator "${expressionId}".`);
626
+ }
627
+ if (!targetChild || targetChild.parentId !== expressionId) {
628
+ throw new Error(`Expression "${targetChildId}" is not a child of operator "${expressionId}".`);
629
+ }
630
+ // Determine position for the formula buffer (min of the two children)
631
+ const formulaPosition = Math.min(sourceChild.position, targetChild.position);
632
+ // Create the sub-operator and formula first as detached nodes,
633
+ // then reparent children away from the parent (freeing their
634
+ // position slots), and finally add formula + sub-operator.
635
+ const formulaId = this.generateId();
636
+ const newOpId = this.generateId();
637
+ // Reparent source and target children to a temporary holding
638
+ // position under the new sub-operator. We must reparent them
639
+ // away from the parent BEFORE adding the formula at their old
640
+ // position slot.
641
+ const firstChild = sourceChild.position <= targetChild.position
642
+ ? sourceChild
643
+ : targetChild;
644
+ const secondChild = sourceChild.position <= targetChild.position
645
+ ? targetChild
646
+ : sourceChild;
647
+ // Reparent children to null temporarily (detach from parent)
648
+ // so their position slots are freed.
649
+ this.expressions.reparentExpression(firstChild.id, null, firstChild.position);
650
+ this.expressions.reparentExpression(secondChild.id, null, secondChild.position);
651
+ // Now add the formula buffer at the freed position
652
+ const formulaExpr = {
653
+ ...extraFields,
654
+ id: formulaId,
655
+ argumentId: target.argumentId,
656
+ argumentVersion: target.argumentVersion,
657
+ premiseId: target.premiseId,
658
+ type: "formula",
659
+ parentId: expressionId,
660
+ position: formulaPosition,
661
+ };
662
+ this.expressions.addExpression(formulaExpr);
663
+ // Add the new sub-operator under the formula
664
+ const newOpExpr = {
665
+ ...extraFields,
666
+ id: newOpId,
667
+ argumentId: target.argumentId,
668
+ argumentVersion: target.argumentVersion,
669
+ premiseId: target.premiseId,
670
+ type: "operator",
671
+ operator: newOperator,
672
+ parentId: formulaId,
673
+ position: POSITION_INITIAL,
674
+ };
675
+ this.expressions.addExpression(newOpExpr);
676
+ // Now reparent the children under the new sub-operator
677
+ this.expressions.reparentExpression(firstChild.id, newOpId, POSITION_INITIAL);
678
+ this.expressions.reparentExpression(secondChild.id, newOpId, midpoint(POSITION_INITIAL, POSITION_MAX));
679
+ const changes = this.finalizeExpressionMutation(collector);
680
+ return {
681
+ result: this.expressions.getExpression(newOpId),
682
+ changes,
683
+ };
684
+ }
685
+ }
686
+ finally {
687
+ this.expressions.setCollector(null);
688
+ }
689
+ });
690
+ }
691
+ getExpression(id) {
692
+ return this.expressions.getExpression(id);
693
+ }
694
+ getId() {
695
+ return this.premise.id;
696
+ }
697
+ getExtras() {
698
+ const { id: _id, argumentId: _argumentId, argumentVersion: _argumentVersion, checksum: _checksum, descendantChecksum: _descendantChecksum, combinedChecksum: _combinedChecksum, ...extras } = this.premise;
699
+ return { ...extras };
700
+ }
701
+ setExtras(extras) {
702
+ return this.withValidation(() => {
703
+ // Strip old extras and replace with new ones
704
+ const { id, argumentId, argumentVersion, checksum, descendantChecksum, combinedChecksum, } = this.premise;
705
+ this.premise = {
706
+ ...extras,
707
+ id,
708
+ argumentId,
709
+ argumentVersion,
710
+ ...(checksum !== undefined ? { checksum } : {}),
711
+ ...(descendantChecksum !== undefined
712
+ ? { descendantChecksum }
713
+ : {}),
714
+ ...(combinedChecksum !== undefined ? { combinedChecksum } : {}),
715
+ };
716
+ this.markDirty();
717
+ this.onMutate?.();
718
+ return { result: this.getExtras(), changes: {} };
719
+ });
720
+ }
721
+ getRootExpressionId() {
722
+ return this.rootExpressionId;
723
+ }
724
+ getRootExpression() {
725
+ if (this.rootExpressionId === undefined) {
726
+ return undefined;
727
+ }
728
+ return this.expressions.getExpression(this.rootExpressionId);
729
+ }
730
+ getVariables() {
731
+ return sortedCopyById(this.variables.toArray());
732
+ }
733
+ getExpressions() {
734
+ return sortedCopyById(this.expressions.toArray());
735
+ }
736
+ getChildExpressions(parentId) {
737
+ return this.expressions.getChildExpressions(parentId);
738
+ }
739
+ isInference() {
740
+ const root = this.getRootExpression();
741
+ return (root?.type === "operator" &&
742
+ (root.operator === "implies" || root.operator === "iff"));
743
+ }
744
+ isConstraint() {
745
+ return !this.isInference();
746
+ }
747
+ validateEvaluability() {
748
+ const issues = [];
749
+ const roots = this.expressions.getChildExpressions(null);
750
+ if (this.expressions.toArray().length === 0) {
751
+ issues.push(makeErrorIssue({
752
+ code: "PREMISE_EMPTY",
753
+ message: `Premise "${this.premise.id}" has no expressions to evaluate.`,
754
+ premiseId: this.premise.id,
755
+ }));
756
+ return makeValidationResult(issues);
757
+ }
758
+ if (roots.length === 0) {
759
+ issues.push(makeErrorIssue({
760
+ code: "PREMISE_ROOT_MISSING",
761
+ message: `Premise "${this.premise.id}" has expressions but no root expression.`,
762
+ premiseId: this.premise.id,
763
+ }));
764
+ }
765
+ if (this.rootExpressionId === undefined) {
766
+ issues.push(makeErrorIssue({
767
+ code: "PREMISE_ROOT_MISSING",
768
+ message: `Premise "${this.premise.id}" does not have rootExpressionId set.`,
769
+ premiseId: this.premise.id,
770
+ }));
771
+ }
772
+ else if (!this.expressions.getExpression(this.rootExpressionId)) {
773
+ issues.push(makeErrorIssue({
774
+ code: "PREMISE_ROOT_MISMATCH",
775
+ message: `Premise "${this.premise.id}" rootExpressionId "${this.rootExpressionId}" does not exist.`,
776
+ premiseId: this.premise.id,
777
+ expressionId: this.rootExpressionId,
778
+ }));
779
+ }
780
+ else if (roots[0] && roots[0].id !== this.rootExpressionId) {
781
+ issues.push(makeErrorIssue({
782
+ code: "PREMISE_ROOT_MISMATCH",
783
+ message: `Premise "${this.premise.id}" rootExpressionId "${this.rootExpressionId}" does not match actual root "${roots[0].id}".`,
784
+ premiseId: this.premise.id,
785
+ expressionId: this.rootExpressionId,
786
+ }));
787
+ }
788
+ for (const expr of this.expressions.toArray()) {
789
+ if (expr.type === "variable" &&
790
+ !this.variables.hasVariable(expr.variableId)) {
791
+ issues.push(makeErrorIssue({
792
+ code: "EXPR_VARIABLE_UNDECLARED",
793
+ message: `Expression "${expr.id}" references undeclared variable "${expr.variableId}".`,
794
+ premiseId: this.premise.id,
795
+ expressionId: expr.id,
796
+ variableId: expr.variableId,
797
+ }));
798
+ }
799
+ if (expr.type === "variable" &&
800
+ this.emptyBoundPremiseCheck?.(expr.variableId)) {
801
+ issues.push({
802
+ code: "EXPR_BOUND_PREMISE_EMPTY",
803
+ severity: "warning",
804
+ message: `Variable "${expr.variableId}" is bound to a premise with no expression tree`,
805
+ expressionId: expr.id,
806
+ });
807
+ }
808
+ if (expr.type !== "operator" && expr.type !== "formula") {
809
+ continue;
810
+ }
811
+ const children = this.expressions.getChildExpressions(expr.id);
812
+ if (expr.type === "formula") {
813
+ if (children.length !== 1) {
814
+ issues.push(makeErrorIssue({
815
+ code: "EXPR_CHILD_COUNT_INVALID",
816
+ message: `Formula expression "${expr.id}" must have exactly 1 child; found ${children.length}.`,
817
+ premiseId: this.premise.id,
818
+ expressionId: expr.id,
819
+ }));
820
+ }
821
+ continue;
822
+ }
823
+ if (expr.operator === "not" && children.length !== 1) {
824
+ issues.push(makeErrorIssue({
825
+ code: "EXPR_CHILD_COUNT_INVALID",
826
+ message: `Operator "${expr.id}" (not) must have exactly 1 child; found ${children.length}.`,
827
+ premiseId: this.premise.id,
828
+ expressionId: expr.id,
829
+ }));
830
+ }
831
+ if ((expr.operator === "implies" || expr.operator === "iff") &&
832
+ children.length !== 2) {
833
+ issues.push(makeErrorIssue({
834
+ code: "EXPR_CHILD_COUNT_INVALID",
835
+ message: `Operator "${expr.id}" (${expr.operator}) must have exactly 2 children; found ${children.length}.`,
836
+ premiseId: this.premise.id,
837
+ expressionId: expr.id,
838
+ }));
839
+ }
840
+ if ((expr.operator === "and" || expr.operator === "or") &&
841
+ children.length < 2) {
842
+ issues.push(makeErrorIssue({
843
+ code: "EXPR_CHILD_COUNT_INVALID",
844
+ message: `Operator "${expr.id}" (${expr.operator}) must have at least 2 children; found ${children.length}.`,
845
+ premiseId: this.premise.id,
846
+ expressionId: expr.id,
847
+ }));
848
+ }
849
+ if (expr.operator === "implies" || expr.operator === "iff") {
850
+ const childPositions = new Set(children.map((child) => child.position));
851
+ if (children.length !== 2 || childPositions.size !== 2) {
852
+ issues.push(makeErrorIssue({
853
+ code: "EXPR_BINARY_POSITIONS_INVALID",
854
+ message: `Operator "${expr.id}" (${expr.operator}) must have exactly 2 children with distinct positions.`,
855
+ premiseId: this.premise.id,
856
+ expressionId: expr.id,
857
+ }));
858
+ }
859
+ }
860
+ }
861
+ return makeValidationResult(issues);
862
+ }
863
+ evaluate(assignment, options) {
864
+ const validation = this.validateEvaluability();
865
+ if (!validation.ok) {
866
+ throw new Error(`Premise "${this.premise.id}" is not evaluable: ${validation.issues
867
+ .map((issue) => issue.code)
868
+ .join(", ")}`);
869
+ }
870
+ const rootExpressionId = this.rootExpressionId;
871
+ const referencedVariableIds = sortedUnique(this.expressions
872
+ .toArray()
873
+ .filter((expr) => expr.type === "variable")
874
+ .map((expr) => expr.variableId));
875
+ if (options?.strictUnknownKeys || options?.requireExactCoverage) {
876
+ const knownVariableIds = new Set(referencedVariableIds);
877
+ const unknownKeys = Object.keys(assignment.variables).filter((variableId) => !knownVariableIds.has(variableId));
878
+ if (unknownKeys.length > 0) {
879
+ throw new Error(`Assignment contains unknown variable IDs for premise "${this.premise.id}": ${unknownKeys.join(", ")}`);
880
+ }
881
+ }
882
+ const expressionValues = {};
883
+ const evaluateExpression = (expressionId) => {
884
+ const expression = this.expressions.getExpression(expressionId);
885
+ if (!expression) {
886
+ throw new Error(`Expression "${expressionId}" was not found.`);
887
+ }
888
+ const operatorState = assignment.operatorAssignments[expression.id];
889
+ if (operatorState === "rejected") {
890
+ expressionValues[expression.id] = false;
891
+ return false;
892
+ }
893
+ if (expression.type === "variable") {
894
+ let value;
895
+ if (options?.resolver) {
896
+ const variable = this.variables.getVariable(expression.variableId);
897
+ if (variable &&
898
+ isPremiseBound(variable) &&
899
+ !isExternallyBound(variable, this.argument.id)) {
900
+ value = options.resolver(expression.variableId);
901
+ }
902
+ else {
903
+ value =
904
+ assignment.variables[expression.variableId] ?? null;
905
+ }
906
+ }
907
+ else {
908
+ value = assignment.variables[expression.variableId] ?? null;
909
+ }
910
+ expressionValues[expression.id] = value;
911
+ return value;
912
+ }
913
+ const children = this.expressions.getChildExpressions(expression.id);
914
+ let value;
915
+ if (expression.type === "formula") {
916
+ value = evaluateExpression(children[0].id);
917
+ expressionValues[expression.id] = value;
918
+ return value;
919
+ }
920
+ switch (expression.operator) {
921
+ case "not":
922
+ value = kleeneNot(evaluateExpression(children[0].id));
923
+ break;
924
+ case "and":
925
+ value = children.reduce((acc, child) => kleeneAnd(acc, evaluateExpression(child.id)), true);
926
+ break;
927
+ case "or":
928
+ value = children.reduce((acc, child) => kleeneOr(acc, evaluateExpression(child.id)), false);
929
+ break;
930
+ case "implies": {
931
+ const left = children[0];
932
+ const right = children[1];
933
+ value = kleeneImplies(evaluateExpression(left.id), evaluateExpression(right.id));
934
+ break;
935
+ }
936
+ case "iff": {
937
+ const left = children[0];
938
+ const right = children[1];
939
+ value = kleeneIff(evaluateExpression(left.id), evaluateExpression(right.id));
940
+ break;
941
+ }
942
+ }
943
+ expressionValues[expression.id] = value;
944
+ return value;
945
+ };
946
+ const rootValue = evaluateExpression(rootExpressionId);
947
+ const variableValues = {};
948
+ for (const variableId of referencedVariableIds) {
949
+ if (options?.resolver) {
950
+ const variable = this.variables.getVariable(variableId);
951
+ if (variable && isPremiseBound(variable)) {
952
+ variableValues[variableId] = options.resolver(variableId);
953
+ continue;
954
+ }
955
+ }
956
+ variableValues[variableId] =
957
+ assignment.variables[variableId] ?? null;
958
+ }
959
+ let inferenceDiagnostic;
960
+ if (this.isInference() &&
961
+ assignment.operatorAssignments[rootExpressionId] !== "rejected") {
962
+ const root = this.expressions.getExpression(rootExpressionId);
963
+ if (root?.type === "operator") {
964
+ const children = this.expressions.getChildExpressions(root.id);
965
+ const left = children[0];
966
+ const right = children[1];
967
+ if (left && right) {
968
+ const leftValue = expressionValues[left.id];
969
+ const rightValue = expressionValues[right.id];
970
+ if (root.operator === "implies") {
971
+ inferenceDiagnostic = {
972
+ kind: "implies",
973
+ premiseId: this.premise.id,
974
+ rootExpressionId,
975
+ leftValue,
976
+ rightValue,
977
+ rootValue,
978
+ antecedentTrue: leftValue,
979
+ consequentTrue: rightValue,
980
+ isVacuouslyTrue: kleeneNot(leftValue),
981
+ fired: leftValue,
982
+ firedAndHeld: kleeneAnd(leftValue, rightValue),
983
+ };
984
+ }
985
+ else if (root.operator === "iff") {
986
+ const leftToRight = buildDirectionalVacuity(leftValue, rightValue);
987
+ const rightToLeft = buildDirectionalVacuity(rightValue, leftValue);
988
+ inferenceDiagnostic = {
989
+ kind: "iff",
990
+ premiseId: this.premise.id,
991
+ rootExpressionId,
992
+ leftValue,
993
+ rightValue,
994
+ rootValue,
995
+ leftToRight,
996
+ rightToLeft,
997
+ bothSidesTrue: kleeneAnd(leftValue, rightValue),
998
+ bothSidesFalse: kleeneAnd(kleeneNot(leftValue), kleeneNot(rightValue)),
999
+ };
1000
+ }
1001
+ }
1002
+ }
1003
+ }
1004
+ return {
1005
+ premiseId: this.premise.id,
1006
+ premiseType: this.isInference() ? "inference" : "constraint",
1007
+ rootExpressionId,
1008
+ rootValue,
1009
+ expressionValues,
1010
+ variableValues,
1011
+ inferenceDiagnostic,
1012
+ };
1013
+ }
1014
+ toDisplayString() {
1015
+ if (this.rootExpressionId === undefined) {
1016
+ return "";
1017
+ }
1018
+ return this.renderExpression(this.rootExpressionId);
1019
+ }
1020
+ getReferencedVariableIds() {
1021
+ const ids = new Set();
1022
+ for (const expr of this.expressions.toArray()) {
1023
+ if (expr.type === "variable") {
1024
+ ids.add(expr.variableId);
1025
+ }
1026
+ }
1027
+ return ids;
1028
+ }
1029
+ toPremiseData() {
1030
+ this.flushChecksums();
1031
+ return {
1032
+ ...this.premise,
1033
+ checksum: this.cachedMetaChecksum,
1034
+ descendantChecksum: this.cachedDescendantChecksum,
1035
+ combinedChecksum: this.cachedCombinedChecksum,
1036
+ };
1037
+ }
1038
+ checksum() {
1039
+ if (this.checksumDirty || this.cachedMetaChecksum === undefined) {
1040
+ this.flushChecksums();
1041
+ }
1042
+ return this.cachedMetaChecksum;
1043
+ }
1044
+ descendantChecksum() {
1045
+ if (this.checksumDirty || this.cachedDescendantChecksum === undefined) {
1046
+ this.flushChecksums();
1047
+ }
1048
+ return this.cachedDescendantChecksum;
1049
+ }
1050
+ combinedChecksum() {
1051
+ if (this.checksumDirty || this.cachedCombinedChecksum === undefined) {
1052
+ this.flushChecksums();
1053
+ }
1054
+ return this.cachedCombinedChecksum;
1055
+ }
1056
+ getCollectionChecksum(_name) {
1057
+ return this.descendantChecksum();
1058
+ }
1059
+ flushChecksums() {
1060
+ this.expressions.flushExpressionChecksums();
1061
+ const premiseFields = this.checksumConfig?.premiseFields ??
1062
+ DEFAULT_CHECKSUM_CONFIG.premiseFields;
1063
+ this.cachedMetaChecksum = entityChecksum(this.premise, premiseFields);
1064
+ const rootId = this.rootExpressionId;
1065
+ if (rootId) {
1066
+ const rootExpr = this.expressions.getExpression(rootId);
1067
+ this.cachedDescendantChecksum = rootExpr
1068
+ ? rootExpr.combinedChecksum
1069
+ : null;
1070
+ }
1071
+ else {
1072
+ this.cachedDescendantChecksum = null;
1073
+ }
1074
+ this.cachedCombinedChecksum =
1075
+ this.cachedDescendantChecksum === null
1076
+ ? this.cachedMetaChecksum
1077
+ : computeHash(this.cachedMetaChecksum + this.cachedDescendantChecksum);
1078
+ this.checksumDirty = false;
1079
+ }
1080
+ validate() {
1081
+ const violations = [];
1082
+ const premiseId = this.premise.id;
1083
+ // 1. Schema check (use toPremiseData() to include computed checksums)
1084
+ const premiseData = this.toPremiseData();
1085
+ if (!Value.Check(CorePremiseSchema, premiseData)) {
1086
+ violations.push({
1087
+ code: PREMISE_SCHEMA_INVALID,
1088
+ message: `Premise "${premiseId}" does not conform to CorePremiseSchema.`,
1089
+ entityType: "premise",
1090
+ entityId: premiseId,
1091
+ premiseId,
1092
+ });
1093
+ }
1094
+ // 2. Delegate to expression-level validation, attaching premiseId
1095
+ const exprResult = this.expressions.validate();
1096
+ for (const v of exprResult.violations) {
1097
+ violations.push({ ...v, premiseId });
1098
+ }
1099
+ // 3. Root expression consistency
1100
+ if (this.rootExpressionId !== undefined) {
1101
+ const rootExpr = this.expressions.getExpression(this.rootExpressionId);
1102
+ if (!rootExpr) {
1103
+ violations.push({
1104
+ code: PREMISE_ROOT_EXPRESSION_INVALID,
1105
+ message: `Premise "${premiseId}" rootExpressionId "${this.rootExpressionId}" does not exist in expression store.`,
1106
+ entityType: "premise",
1107
+ entityId: premiseId,
1108
+ premiseId,
1109
+ });
1110
+ }
1111
+ else if (rootExpr.parentId !== null) {
1112
+ violations.push({
1113
+ code: PREMISE_ROOT_EXPRESSION_INVALID,
1114
+ message: `Premise "${premiseId}" rootExpressionId "${this.rootExpressionId}" has non-null parentId "${rootExpr.parentId}".`,
1115
+ entityType: "premise",
1116
+ entityId: premiseId,
1117
+ premiseId,
1118
+ });
1119
+ }
1120
+ }
1121
+ // 4. Variable references: every variable-type expression must
1122
+ // reference a variableId that exists in the argument's variable set
1123
+ if (this.variableIdsCallback) {
1124
+ const variableIds = this.variableIdsCallback();
1125
+ for (const expr of this.expressions.toArray()) {
1126
+ if (expr.type === "variable") {
1127
+ const varExpr = expr;
1128
+ if (!variableIds.has(varExpr.variableId)) {
1129
+ violations.push({
1130
+ code: PREMISE_VARIABLE_REF_NOT_FOUND,
1131
+ message: `Expression "${expr.id}" in premise "${premiseId}" references non-existent variable "${varExpr.variableId}".`,
1132
+ entityType: "expression",
1133
+ entityId: expr.id,
1134
+ premiseId,
1135
+ });
1136
+ }
1137
+ }
1138
+ }
1139
+ }
1140
+ return {
1141
+ ok: violations.length === 0,
1142
+ violations,
1143
+ };
1144
+ }
1145
+ // -------------------------------------------------------------------------
1146
+ // Private helpers
1147
+ // -------------------------------------------------------------------------
1148
+ /**
1149
+ * Loads expressions in BFS order with the nesting check bypassed.
1150
+ * Bypasses all PremiseEngine validation (ownership, variable existence, circularity)
1151
+ * since restoration paths trust existing data completely.
1152
+ */
1153
+ loadExpressions(expressions) {
1154
+ this.expressions.loadExpressions(expressions);
1155
+ // Rebuild root and variable tracking after bulk load.
1156
+ for (const expr of this.expressions.toArray()) {
1157
+ if (expr.parentId === null) {
1158
+ this.rootExpressionId = expr.id;
1159
+ }
1160
+ if (expr.type === "variable") {
1161
+ this.expressionsByVariableId.get(expr.variableId).add(expr.id);
1162
+ }
1163
+ if (this.expressionIndex) {
1164
+ this.expressionIndex.set(expr.id, this.premise.id);
1165
+ }
1166
+ }
1167
+ this.markDirty();
1168
+ }
1169
+ markDirty() {
1170
+ this.checksumDirty = true;
1171
+ }
1172
+ /**
1173
+ * Re-reads the single root from ExpressionManager after any operation
1174
+ * that may have caused operator collapse to silently change the root.
1175
+ */
1176
+ syncRootExpressionId() {
1177
+ const roots = this.expressions.getChildExpressions(null);
1178
+ this.rootExpressionId = roots[0]?.id;
1179
+ }
1180
+ collectSubtree(rootId) {
1181
+ const result = [];
1182
+ const stack = [rootId];
1183
+ while (stack.length > 0) {
1184
+ const id = stack.pop();
1185
+ const expr = this.expressions.getExpression(id);
1186
+ if (!expr)
1187
+ continue;
1188
+ result.push(expr);
1189
+ for (const child of this.expressions.getChildExpressions(id)) {
1190
+ stack.push(child.id);
1191
+ }
1192
+ }
1193
+ return result;
1194
+ }
1195
+ assertBelongsToArgument(argumentId, argumentVersion) {
1196
+ if (argumentId !== this.argument.id) {
1197
+ throw new Error(`Entity argumentId "${argumentId}" does not match engine argument ID "${this.argument.id}".`);
1198
+ }
1199
+ if (argumentVersion !== this.argument.version) {
1200
+ throw new Error(`Entity argumentVersion "${argumentVersion}" does not match engine argument version "${this.argument.version}".`);
1201
+ }
1202
+ }
1203
+ assertVariableExpressionValid(expression) {
1204
+ if (expression.type === "variable" &&
1205
+ !this.variables.hasVariable(expression.variableId)) {
1206
+ throw new Error(`Variable expression "${expression.id}" references non-existent variable "${expression.variableId}".`);
1207
+ }
1208
+ if (expression.type === "variable" && this.circularityCheck) {
1209
+ if (this.circularityCheck(expression.variableId, this.premise.id)) {
1210
+ throw new Error(`Circular binding: variable "${expression.variableId}" is bound to this premise (directly or transitively)`);
1211
+ }
1212
+ }
1213
+ }
1214
+ renderExpression(expressionId) {
1215
+ const expression = this.expressions.getExpression(expressionId);
1216
+ if (!expression) {
1217
+ throw new Error(`Expression "${expressionId}" was not found.`);
1218
+ }
1219
+ if (expression.type === "variable") {
1220
+ const variable = this.variables.getVariable(expression.variableId);
1221
+ if (!variable) {
1222
+ throw new Error(`Variable "${expression.variableId}" for expression "${expressionId}" was not found.`);
1223
+ }
1224
+ return variable.symbol;
1225
+ }
1226
+ if (expression.type === "formula") {
1227
+ const children = this.expressions.getChildExpressions(expression.id);
1228
+ if (children.length === 0) {
1229
+ return "(?)";
1230
+ }
1231
+ return `(${this.renderExpression(children[0].id)})`;
1232
+ }
1233
+ const children = this.expressions.getChildExpressions(expression.id);
1234
+ if (expression.operator === "not") {
1235
+ if (children.length === 0) {
1236
+ return `${this.operatorSymbol(expression.operator)} (?)`;
1237
+ }
1238
+ return `${this.operatorSymbol(expression.operator)}(${this.renderExpression(children[0].id)})`;
1239
+ }
1240
+ if (children.length === 0) {
1241
+ return "(?)";
1242
+ }
1243
+ const renderedChildren = children.map((child) => this.renderExpression(child.id));
1244
+ return `(${renderedChildren.join(` ${this.operatorSymbol(expression.operator)} `)})`;
1245
+ }
1246
+ operatorSymbol(operator) {
1247
+ switch (operator) {
1248
+ case "and":
1249
+ return "∧";
1250
+ case "or":
1251
+ return "∨";
1252
+ case "implies":
1253
+ return "→";
1254
+ case "iff":
1255
+ return "↔";
1256
+ case "not":
1257
+ return "¬";
1258
+ }
1259
+ }
1260
+ snapshot() {
1261
+ this.flushChecksums();
1262
+ const exprSnapshot = this.expressions.snapshot();
1263
+ return {
1264
+ premise: {
1265
+ ...this.premise,
1266
+ checksum: this.cachedMetaChecksum,
1267
+ descendantChecksum: this.cachedDescendantChecksum,
1268
+ combinedChecksum: this.cachedCombinedChecksum,
1269
+ },
1270
+ rootExpressionId: this.rootExpressionId,
1271
+ expressions: exprSnapshot,
1272
+ config: {
1273
+ ...exprSnapshot.config,
1274
+ checksumConfig: serializeChecksumConfig(this.checksumConfig),
1275
+ },
1276
+ };
1277
+ }
1278
+ /** Creates a new PremiseEngine from a previously captured snapshot. */
1279
+ static fromSnapshot(snapshot, argument, variables, expressionIndex, grammarConfig, generateId) {
1280
+ // Normalize checksumConfig in case the snapshot went through a JSON
1281
+ // round-trip that converted Sets to arrays or empty objects.
1282
+ const normalizedConfig = snapshot.config
1283
+ ? {
1284
+ ...snapshot.config,
1285
+ checksumConfig: normalizeChecksumConfig(snapshot.config.checksumConfig),
1286
+ generateId: generateId ?? snapshot.config.generateId,
1287
+ }
1288
+ : generateId
1289
+ ? { generateId }
1290
+ : snapshot.config;
1291
+ const pe = new PremiseEngine(snapshot.premise, { argument, variables, expressionIndex }, normalizedConfig);
1292
+ // Restore expressions from the snapshot
1293
+ pe.expressions = ExpressionManager.fromSnapshot(snapshot.expressions, grammarConfig, generateId);
1294
+ // Restore rootExpressionId from snapshot
1295
+ pe.rootExpressionId = snapshot.rootExpressionId;
1296
+ // Rebuild the expressionsByVariableId index
1297
+ pe.rebuildVariableIndex();
1298
+ // Populate the shared expression index if provided
1299
+ if (expressionIndex) {
1300
+ for (const expr of pe.expressions.toArray()) {
1301
+ expressionIndex.set(expr.id, pe.getId());
1302
+ }
1303
+ }
1304
+ return pe;
1305
+ }
1306
+ /**
1307
+ * Flushes hierarchical expression checksums and rebuilds the changeset
1308
+ * so that added/modified expressions carry correct `descendantChecksum`
1309
+ * and `combinedChecksum` values (rather than the stale ones captured
1310
+ * at mutation time by the ChangeCollector).
1311
+ */
1312
+ finalizeExpressionMutation(collector) {
1313
+ this.syncRootExpressionId();
1314
+ this.markDirty();
1315
+ const changes = this.flushAndBuildChangeset(collector);
1316
+ this.syncExpressionIndex(changes);
1317
+ this.onMutate?.();
1318
+ return changes;
1319
+ }
1320
+ flushAndBuildChangeset(collector) {
1321
+ // Snapshot premise combinedChecksum before flush
1322
+ const premiseCombinedBefore = this.cachedCombinedChecksum ?? null;
1323
+ this.expressions.flushExpressionChecksums();
1324
+ const changes = collector.toChangeset();
1325
+ if (changes.expressions) {
1326
+ changes.expressions.added = changes.expressions.added.map((expr) => {
1327
+ const current = this.expressions.getExpression(expr.id);
1328
+ return current ? { ...current } : expr;
1329
+ });
1330
+ changes.expressions.modified = changes.expressions.modified.map((expr) => {
1331
+ const current = this.expressions.getExpression(expr.id);
1332
+ return current ? { ...current } : expr;
1333
+ });
1334
+ }
1335
+ // Recompute premise checksum and include if changed
1336
+ this.flushChecksums();
1337
+ if (this.cachedCombinedChecksum !== premiseCombinedBefore) {
1338
+ changes.premises ??= { added: [], modified: [], removed: [] };
1339
+ changes.premises.modified.push(this.toPremiseData());
1340
+ }
1341
+ return changes;
1342
+ }
1343
+ syncExpressionIndex(changes) {
1344
+ if (!this.expressionIndex || !changes.expressions)
1345
+ return;
1346
+ for (const expr of changes.expressions.added) {
1347
+ this.expressionIndex.set(expr.id, this.premise.id);
1348
+ }
1349
+ for (const expr of changes.expressions.removed) {
1350
+ this.expressionIndex.delete(expr.id);
1351
+ }
1352
+ }
1353
+ rebuildVariableIndex() {
1354
+ this.expressionsByVariableId = new DefaultMap(() => new Set());
1355
+ for (const expr of this.expressions.toArray()) {
1356
+ if (expr.type === "variable") {
1357
+ this.expressionsByVariableId.get(expr.variableId).add(expr.id);
1358
+ }
1359
+ }
1360
+ }
1361
+ }
1362
+ //# sourceMappingURL=premise-engine.js.map