universal-physics-tensor 0.47.0 → 1.0.1

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 (591) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +396 -383
  3. package/bin/upt.mjs +28 -22
  4. package/dist/atlas/benchmark/hybrid-retrieval.d.ts +108 -0
  5. package/dist/atlas/benchmark/hybrid-retrieval.d.ts.map +1 -0
  6. package/dist/atlas/benchmark/hybrid-retrieval.js +241 -0
  7. package/dist/atlas/benchmark/hybrid-retrieval.js.map +1 -0
  8. package/dist/atlas/catalog-formal-ref.d.ts +24 -0
  9. package/dist/atlas/catalog-formal-ref.d.ts.map +1 -0
  10. package/dist/atlas/catalog-formal-ref.js +36 -0
  11. package/dist/atlas/catalog-formal-ref.js.map +1 -0
  12. package/dist/atlas/composition-table.d.ts +11 -46
  13. package/dist/atlas/composition-table.d.ts.map +1 -1
  14. package/dist/atlas/composition-table.js +7 -124
  15. package/dist/atlas/composition-table.js.map +1 -1
  16. package/dist/atlas/conventions.d.ts +4 -58
  17. package/dist/atlas/conventions.d.ts.map +1 -1
  18. package/dist/atlas/conventions.js +3 -88
  19. package/dist/atlas/conventions.js.map +1 -1
  20. package/dist/atlas/derive-evidence.d.ts +50 -3
  21. package/dist/atlas/derive-evidence.d.ts.map +1 -1
  22. package/dist/atlas/derive-evidence.js +73 -4
  23. package/dist/atlas/derive-evidence.js.map +1 -1
  24. package/dist/atlas/diffusion/bridges-closure.d.ts.map +1 -1
  25. package/dist/atlas/diffusion/bridges-closure.js +5 -1
  26. package/dist/atlas/diffusion/bridges-closure.js.map +1 -1
  27. package/dist/atlas/index.d.ts +9 -7
  28. package/dist/atlas/index.d.ts.map +1 -1
  29. package/dist/atlas/index.js +6 -5
  30. package/dist/atlas/index.js.map +1 -1
  31. package/dist/atlas/oscillators/bridges-exact.d.ts.map +1 -1
  32. package/dist/atlas/oscillators/bridges-exact.js +6 -0
  33. package/dist/atlas/oscillators/bridges-exact.js.map +1 -1
  34. package/dist/atlas/oscillators/bridges-limits.d.ts +2 -0
  35. package/dist/atlas/oscillators/bridges-limits.d.ts.map +1 -1
  36. package/dist/atlas/oscillators/bridges-limits.js +20 -19
  37. package/dist/atlas/oscillators/bridges-limits.js.map +1 -1
  38. package/dist/atlas/oscillators/limit-witnesses.d.ts +93 -0
  39. package/dist/atlas/oscillators/limit-witnesses.d.ts.map +1 -0
  40. package/dist/atlas/oscillators/limit-witnesses.js +152 -0
  41. package/dist/atlas/oscillators/limit-witnesses.js.map +1 -0
  42. package/dist/atlas/oscillators/models.d.ts +2 -1
  43. package/dist/atlas/oscillators/models.d.ts.map +1 -1
  44. package/dist/atlas/oscillators/models.js +4 -3
  45. package/dist/atlas/oscillators/models.js.map +1 -1
  46. package/dist/atlas/oscillators/norm-transport-witness.d.ts +37 -0
  47. package/dist/atlas/oscillators/norm-transport-witness.d.ts.map +1 -0
  48. package/dist/atlas/oscillators/norm-transport-witness.js +58 -0
  49. package/dist/atlas/oscillators/norm-transport-witness.js.map +1 -0
  50. package/dist/atlas/oscillators/norm-transport.d.ts +44 -0
  51. package/dist/atlas/oscillators/norm-transport.d.ts.map +1 -0
  52. package/dist/atlas/oscillators/norm-transport.js +66 -0
  53. package/dist/atlas/oscillators/norm-transport.js.map +1 -0
  54. package/dist/atlas/oscillators/norms.d.ts +11 -0
  55. package/dist/atlas/oscillators/norms.d.ts.map +1 -0
  56. package/dist/atlas/oscillators/norms.js +11 -0
  57. package/dist/atlas/oscillators/norms.js.map +1 -0
  58. package/dist/atlas/oscillators/pendulum-motion.d.ts +38 -0
  59. package/dist/atlas/oscillators/pendulum-motion.d.ts.map +1 -0
  60. package/dist/atlas/oscillators/pendulum-motion.js +122 -0
  61. package/dist/atlas/oscillators/pendulum-motion.js.map +1 -0
  62. package/dist/atlas/oscillators/phase-carriage.d.ts +38 -0
  63. package/dist/atlas/oscillators/phase-carriage.d.ts.map +1 -0
  64. package/dist/atlas/oscillators/phase-carriage.js +96 -0
  65. package/dist/atlas/oscillators/phase-carriage.js.map +1 -0
  66. package/dist/atlas/oscillators/phase-translation.d.ts +46 -0
  67. package/dist/atlas/oscillators/phase-translation.d.ts.map +1 -0
  68. package/dist/atlas/oscillators/phase-translation.js +178 -0
  69. package/dist/atlas/oscillators/phase-translation.js.map +1 -0
  70. package/dist/atlas/oscillators/position-translation.d.ts +59 -0
  71. package/dist/atlas/oscillators/position-translation.d.ts.map +1 -0
  72. package/dist/atlas/oscillators/position-translation.js +254 -0
  73. package/dist/atlas/oscillators/position-translation.js.map +1 -0
  74. package/dist/atlas/path-bound.d.ts +126 -9
  75. package/dist/atlas/path-bound.d.ts.map +1 -1
  76. package/dist/atlas/path-bound.js +372 -23
  77. package/dist/atlas/path-bound.js.map +1 -1
  78. package/dist/atlas/physjs-ref.d.ts +112 -0
  79. package/dist/atlas/physjs-ref.d.ts.map +1 -0
  80. package/dist/atlas/physjs-ref.js +842 -0
  81. package/dist/atlas/physjs-ref.js.map +1 -0
  82. package/dist/atlas/regime.d.ts +12 -136
  83. package/dist/atlas/regime.d.ts.map +1 -1
  84. package/dist/atlas/regime.js +8 -254
  85. package/dist/atlas/regime.js.map +1 -1
  86. package/dist/atlas/serialize.d.ts.map +1 -1
  87. package/dist/atlas/serialize.js +25 -0
  88. package/dist/atlas/serialize.js.map +1 -1
  89. package/dist/atlas/translation-registry.d.ts +22 -0
  90. package/dist/atlas/translation-registry.d.ts.map +1 -0
  91. package/dist/atlas/translation-registry.js +31 -0
  92. package/dist/atlas/translation-registry.js.map +1 -0
  93. package/dist/atlas/translation.d.ts +116 -0
  94. package/dist/atlas/translation.d.ts.map +1 -0
  95. package/dist/atlas/translation.js +34 -0
  96. package/dist/atlas/translation.js.map +1 -0
  97. package/dist/atlas/types.d.ts +74 -240
  98. package/dist/atlas/types.d.ts.map +1 -1
  99. package/dist/atlas/types.js +5 -37
  100. package/dist/atlas/types.js.map +1 -1
  101. package/dist/atlas/waves/bridges-closure.d.ts.map +1 -1
  102. package/dist/atlas/waves/bridges-closure.js +4 -0
  103. package/dist/atlas/waves/bridges-closure.js.map +1 -1
  104. package/dist/atlas/waves/bridges.d.ts.map +1 -1
  105. package/dist/atlas/waves/bridges.js +3 -0
  106. package/dist/atlas/waves/bridges.js.map +1 -1
  107. package/dist/atlas/waves/models.js +1 -1
  108. package/dist/atlas/waves/models.js.map +1 -1
  109. package/dist/atlas/witness-dominance.d.ts +50 -0
  110. package/dist/atlas/witness-dominance.d.ts.map +1 -0
  111. package/dist/atlas/witness-dominance.js +86 -0
  112. package/dist/atlas/witness-dominance.js.map +1 -0
  113. package/dist/atlas/witness-specs.d.ts +30 -0
  114. package/dist/atlas/witness-specs.d.ts.map +1 -1
  115. package/dist/atlas/witness-specs.js +107 -0
  116. package/dist/atlas/witness-specs.js.map +1 -1
  117. package/dist/bridges/be53-yang-mills-confrontation.d.ts +81 -0
  118. package/dist/bridges/be53-yang-mills-confrontation.d.ts.map +1 -0
  119. package/dist/bridges/be53-yang-mills-confrontation.js +110 -0
  120. package/dist/bridges/be53-yang-mills-confrontation.js.map +1 -0
  121. package/dist/bridges/confrontations.d.ts +1 -1
  122. package/dist/bridges/confrontations.d.ts.map +1 -1
  123. package/dist/bridges/confrontations.js +291 -3
  124. package/dist/bridges/confrontations.js.map +1 -1
  125. package/dist/bridges/equations/be-13-einstein-trace.d.ts +2 -3
  126. package/dist/bridges/equations/be-13-einstein-trace.d.ts.map +1 -1
  127. package/dist/bridges/equations/be-13-einstein-trace.js +2 -3
  128. package/dist/bridges/equations/be-13-einstein-trace.js.map +1 -1
  129. package/dist/bridges/equations/be-38-mond.d.ts +7 -5
  130. package/dist/bridges/equations/be-38-mond.d.ts.map +1 -1
  131. package/dist/bridges/equations/be-38-mond.js +7 -5
  132. package/dist/bridges/equations/be-38-mond.js.map +1 -1
  133. package/dist/bridges/equations/be-53-yang-mills-beta.d.ts +21 -0
  134. package/dist/bridges/equations/be-53-yang-mills-beta.d.ts.map +1 -1
  135. package/dist/bridges/equations/be-53-yang-mills-beta.js +12 -0
  136. package/dist/bridges/equations/be-53-yang-mills-beta.js.map +1 -1
  137. package/dist/bridges/evaluator-inputs.d.ts +21 -0
  138. package/dist/bridges/evaluator-inputs.d.ts.map +1 -0
  139. package/dist/bridges/evaluator-inputs.js +75 -0
  140. package/dist/bridges/evaluator-inputs.js.map +1 -0
  141. package/dist/bridges/evaluators.d.ts +38 -0
  142. package/dist/bridges/evaluators.d.ts.map +1 -1
  143. package/dist/bridges/evaluators.js +41 -15
  144. package/dist/bridges/evaluators.js.map +1 -1
  145. package/dist/bridges/gravitational-lensing.d.ts +1 -1
  146. package/dist/bridges/gravitational-lensing.js +1 -1
  147. package/dist/bridges/index.d.ts +1 -1
  148. package/dist/bridges/index.d.ts.map +1 -1
  149. package/dist/bridges/index.js +13 -13
  150. package/dist/bridges/index.js.map +1 -1
  151. package/dist/bridges/observations/types.d.ts +110 -2
  152. package/dist/bridges/observations/types.d.ts.map +1 -1
  153. package/dist/bridges/observations/types.js +29 -0
  154. package/dist/bridges/observations/types.js.map +1 -1
  155. package/dist/bridges/perihelion-precession.d.ts +1 -1
  156. package/dist/bridges/perihelion-precession.js +1 -1
  157. package/dist/canonical/canonical-equation.d.ts +1 -1
  158. package/dist/canonical/canonical-equation.d.ts.map +1 -1
  159. package/dist/canonical/entries/atomic.d.ts.map +1 -1
  160. package/dist/canonical/entries/atomic.js +32 -10
  161. package/dist/canonical/entries/atomic.js.map +1 -1
  162. package/dist/canonical/entries/dimensional-classics.js +2 -2
  163. package/dist/canonical/entries/dimensional-classics.js.map +1 -1
  164. package/dist/canonical/entries/mechanics.d.ts.map +1 -1
  165. package/dist/canonical/entries/mechanics.js +10 -6
  166. package/dist/canonical/entries/mechanics.js.map +1 -1
  167. package/dist/canonical/entries/relativity.d.ts.map +1 -1
  168. package/dist/canonical/entries/relativity.js +41 -8
  169. package/dist/canonical/entries/relativity.js.map +1 -1
  170. package/dist/canonical/entries/thermo-nuclear-cosmo.js +5 -5
  171. package/dist/canonical/entries/thermo-nuclear-cosmo.js.map +1 -1
  172. package/dist/canonical/linkage.d.ts.map +1 -1
  173. package/dist/canonical/linkage.js +14 -8
  174. package/dist/canonical/linkage.js.map +1 -1
  175. package/dist/canonical/normal-form.d.ts +17 -0
  176. package/dist/canonical/normal-form.d.ts.map +1 -1
  177. package/dist/canonical/normal-form.js +21 -4
  178. package/dist/canonical/normal-form.js.map +1 -1
  179. package/dist/cases/brownian-sphere.d.ts +68 -0
  180. package/dist/cases/brownian-sphere.d.ts.map +1 -0
  181. package/dist/cases/brownian-sphere.js +353 -0
  182. package/dist/cases/brownian-sphere.js.map +1 -0
  183. package/dist/cases/damped-resonator.d.ts +23 -0
  184. package/dist/cases/damped-resonator.d.ts.map +1 -0
  185. package/dist/cases/damped-resonator.js +224 -0
  186. package/dist/cases/damped-resonator.js.map +1 -0
  187. package/dist/cases/index.d.ts +11 -0
  188. package/dist/cases/index.d.ts.map +1 -0
  189. package/dist/cases/index.js +29 -0
  190. package/dist/cases/index.js.map +1 -0
  191. package/dist/cases/kepler-rv.d.ts +13 -0
  192. package/dist/cases/kepler-rv.d.ts.map +1 -0
  193. package/dist/cases/kepler-rv.js +168 -0
  194. package/dist/cases/kepler-rv.js.map +1 -0
  195. package/dist/cases/lumped-cooling.d.ts +46 -0
  196. package/dist/cases/lumped-cooling.d.ts.map +1 -0
  197. package/dist/cases/lumped-cooling.js +261 -0
  198. package/dist/cases/lumped-cooling.js.map +1 -0
  199. package/dist/cases/quadrature.d.ts +14 -0
  200. package/dist/cases/quadrature.d.ts.map +1 -0
  201. package/dist/cases/quadrature.js +41 -0
  202. package/dist/cases/quadrature.js.map +1 -0
  203. package/dist/cases/resistor-noise.d.ts +14 -0
  204. package/dist/cases/resistor-noise.d.ts.map +1 -0
  205. package/dist/cases/resistor-noise.js +210 -0
  206. package/dist/cases/resistor-noise.js.map +1 -0
  207. package/dist/cases/skin-depth.d.ts +21 -0
  208. package/dist/cases/skin-depth.d.ts.map +1 -0
  209. package/dist/cases/skin-depth.js +174 -0
  210. package/dist/cases/skin-depth.js.map +1 -0
  211. package/dist/cases/types.d.ts +115 -0
  212. package/dist/cases/types.d.ts.map +1 -0
  213. package/dist/cases/types.js +20 -0
  214. package/dist/cases/types.js.map +1 -0
  215. package/dist/cli/commands/_atlas-map.d.ts +409 -0
  216. package/dist/cli/commands/_atlas-map.d.ts.map +1 -0
  217. package/dist/cli/commands/_atlas-map.js +1014 -0
  218. package/dist/cli/commands/_atlas-map.js.map +1 -0
  219. package/dist/cli/commands/_atlas-route.d.ts +111 -0
  220. package/dist/cli/commands/_atlas-route.d.ts.map +1 -0
  221. package/dist/cli/commands/_atlas-route.js +140 -0
  222. package/dist/cli/commands/_atlas-route.js.map +1 -0
  223. package/dist/cli/commands/_discovery-opts.d.ts.map +1 -1
  224. package/dist/cli/commands/_discovery-opts.js +10 -1
  225. package/dist/cli/commands/_discovery-opts.js.map +1 -1
  226. package/dist/cli/commands/atlas.d.ts +20 -0
  227. package/dist/cli/commands/atlas.d.ts.map +1 -1
  228. package/dist/cli/commands/atlas.js +333 -19
  229. package/dist/cli/commands/atlas.js.map +1 -1
  230. package/dist/cli/commands/audit.d.ts.map +1 -1
  231. package/dist/cli/commands/audit.js +14 -5
  232. package/dist/cli/commands/audit.js.map +1 -1
  233. package/dist/cli/commands/axes.js +4 -4
  234. package/dist/cli/commands/candidates.d.ts.map +1 -1
  235. package/dist/cli/commands/candidates.js +6 -5
  236. package/dist/cli/commands/candidates.js.map +1 -1
  237. package/dist/cli/commands/canonical.d.ts.map +1 -1
  238. package/dist/cli/commands/canonical.js +41 -12
  239. package/dist/cli/commands/canonical.js.map +1 -1
  240. package/dist/cli/commands/confront.d.ts.map +1 -1
  241. package/dist/cli/commands/confront.js +210 -28
  242. package/dist/cli/commands/confront.js.map +1 -1
  243. package/dist/cli/commands/connectors.d.ts.map +1 -1
  244. package/dist/cli/commands/connectors.js +11 -10
  245. package/dist/cli/commands/connectors.js.map +1 -1
  246. package/dist/cli/commands/coverage.js +3 -3
  247. package/dist/cli/commands/derive.d.ts.map +1 -1
  248. package/dist/cli/commands/derive.js +22 -10
  249. package/dist/cli/commands/derive.js.map +1 -1
  250. package/dist/cli/commands/discover.d.ts.map +1 -1
  251. package/dist/cli/commands/discover.js +149 -32
  252. package/dist/cli/commands/discover.js.map +1 -1
  253. package/dist/cli/commands/eval.d.ts.map +1 -1
  254. package/dist/cli/commands/eval.js +76 -17
  255. package/dist/cli/commands/eval.js.map +1 -1
  256. package/dist/cli/commands/evaluate.d.ts +30 -0
  257. package/dist/cli/commands/evaluate.d.ts.map +1 -1
  258. package/dist/cli/commands/evaluate.js +440 -25
  259. package/dist/cli/commands/evaluate.js.map +1 -1
  260. package/dist/cli/commands/explain.d.ts.map +1 -1
  261. package/dist/cli/commands/explain.js +38 -11
  262. package/dist/cli/commands/explain.js.map +1 -1
  263. package/dist/cli/commands/frontier.d.ts +3 -0
  264. package/dist/cli/commands/frontier.d.ts.map +1 -0
  265. package/dist/cli/commands/frontier.js +28 -0
  266. package/dist/cli/commands/frontier.js.map +1 -0
  267. package/dist/cli/commands/ground.d.ts.map +1 -1
  268. package/dist/cli/commands/ground.js +37 -12
  269. package/dist/cli/commands/ground.js.map +1 -1
  270. package/dist/cli/commands/index.d.ts +5 -0
  271. package/dist/cli/commands/index.d.ts.map +1 -1
  272. package/dist/cli/commands/index.js +5 -0
  273. package/dist/cli/commands/index.js.map +1 -1
  274. package/dist/cli/commands/map.d.ts +8 -0
  275. package/dist/cli/commands/map.d.ts.map +1 -1
  276. package/dist/cli/commands/map.js +401 -64
  277. package/dist/cli/commands/map.js.map +1 -1
  278. package/dist/cli/commands/metric.d.ts +3 -0
  279. package/dist/cli/commands/metric.d.ts.map +1 -0
  280. package/dist/cli/commands/metric.js +136 -0
  281. package/dist/cli/commands/metric.js.map +1 -0
  282. package/dist/cli/commands/path.d.ts +109 -1
  283. package/dist/cli/commands/path.d.ts.map +1 -1
  284. package/dist/cli/commands/path.js +1019 -109
  285. package/dist/cli/commands/path.js.map +1 -1
  286. package/dist/cli/commands/predict.d.ts.map +1 -1
  287. package/dist/cli/commands/predict.js +6 -5
  288. package/dist/cli/commands/predict.js.map +1 -1
  289. package/dist/cli/commands/priority.d.ts.map +1 -1
  290. package/dist/cli/commands/priority.js +4 -3
  291. package/dist/cli/commands/priority.js.map +1 -1
  292. package/dist/cli/commands/probe.d.ts +7 -0
  293. package/dist/cli/commands/probe.d.ts.map +1 -1
  294. package/dist/cli/commands/probe.js +234 -52
  295. package/dist/cli/commands/probe.js.map +1 -1
  296. package/dist/cli/commands/recover.d.ts.map +1 -1
  297. package/dist/cli/commands/recover.js +17 -6
  298. package/dist/cli/commands/recover.js.map +1 -1
  299. package/dist/cli/commands/regime.d.ts +1 -1
  300. package/dist/cli/commands/regime.d.ts.map +1 -1
  301. package/dist/cli/commands/regime.js +134 -33
  302. package/dist/cli/commands/regime.js.map +1 -1
  303. package/dist/cli/commands/retrieve.d.ts +3 -0
  304. package/dist/cli/commands/retrieve.d.ts.map +1 -0
  305. package/dist/cli/commands/retrieve.js +65 -0
  306. package/dist/cli/commands/retrieve.js.map +1 -0
  307. package/dist/cli/commands/search.d.ts +3 -0
  308. package/dist/cli/commands/search.d.ts.map +1 -0
  309. package/dist/cli/commands/search.js +70 -0
  310. package/dist/cli/commands/search.js.map +1 -0
  311. package/dist/cli/commands/symbolic.d.ts.map +1 -1
  312. package/dist/cli/commands/symbolic.js +112 -21
  313. package/dist/cli/commands/symbolic.js.map +1 -1
  314. package/dist/cli/commands/testplan.d.ts +3 -0
  315. package/dist/cli/commands/testplan.d.ts.map +1 -0
  316. package/dist/cli/commands/testplan.js +131 -0
  317. package/dist/cli/commands/testplan.js.map +1 -0
  318. package/dist/cli/conventions.d.ts +22 -0
  319. package/dist/cli/conventions.d.ts.map +1 -0
  320. package/dist/cli/conventions.js +48 -0
  321. package/dist/cli/conventions.js.map +1 -0
  322. package/dist/cli/euler-guard.d.ts +9 -0
  323. package/dist/cli/euler-guard.d.ts.map +1 -0
  324. package/dist/cli/euler-guard.js +11 -0
  325. package/dist/cli/euler-guard.js.map +1 -0
  326. package/dist/cli/eval-numbers.d.ts +26 -0
  327. package/dist/cli/eval-numbers.d.ts.map +1 -0
  328. package/dist/cli/eval-numbers.js +49 -0
  329. package/dist/cli/eval-numbers.js.map +1 -0
  330. package/dist/cli/expr-print.d.ts +25 -0
  331. package/dist/cli/expr-print.d.ts.map +1 -0
  332. package/dist/cli/expr-print.js +123 -0
  333. package/dist/cli/expr-print.js.map +1 -0
  334. package/dist/cli/graphs.d.ts +26 -0
  335. package/dist/cli/graphs.d.ts.map +1 -1
  336. package/dist/cli/graphs.js +19 -0
  337. package/dist/cli/graphs.js.map +1 -1
  338. package/dist/cli/main.d.ts +4 -10
  339. package/dist/cli/main.d.ts.map +1 -1
  340. package/dist/cli/main.js +370 -167
  341. package/dist/cli/main.js.map +1 -1
  342. package/dist/cli/map-evidence.d.ts +47 -0
  343. package/dist/cli/map-evidence.d.ts.map +1 -0
  344. package/dist/cli/map-evidence.js +53 -0
  345. package/dist/cli/map-evidence.js.map +1 -0
  346. package/dist/cli/output.d.ts +21 -1
  347. package/dist/cli/output.d.ts.map +1 -1
  348. package/dist/cli/output.js +5 -1
  349. package/dist/cli/output.js.map +1 -1
  350. package/dist/{composition → cli}/poster-source.d.ts +3 -2
  351. package/dist/cli/poster-source.d.ts.map +1 -0
  352. package/dist/{composition → cli}/poster-source.js +2 -1
  353. package/dist/cli/poster-source.js.map +1 -0
  354. package/dist/cli/record-reach.d.ts +44 -0
  355. package/dist/cli/record-reach.d.ts.map +1 -0
  356. package/dist/cli/record-reach.js +228 -0
  357. package/dist/cli/record-reach.js.map +1 -0
  358. package/dist/cli/record-tables.d.ts +38 -0
  359. package/dist/cli/record-tables.d.ts.map +1 -0
  360. package/dist/cli/record-tables.js +110 -0
  361. package/dist/cli/record-tables.js.map +1 -0
  362. package/dist/cli/record.d.ts +141 -0
  363. package/dist/cli/record.d.ts.map +1 -0
  364. package/dist/cli/record.js +612 -0
  365. package/dist/cli/record.js.map +1 -0
  366. package/dist/cli/search-index.d.ts +56 -0
  367. package/dist/cli/search-index.d.ts.map +1 -0
  368. package/dist/cli/search-index.js +190 -0
  369. package/dist/cli/search-index.js.map +1 -0
  370. package/dist/cli/statuses.d.ts +25 -0
  371. package/dist/cli/statuses.d.ts.map +1 -0
  372. package/dist/cli/statuses.js +276 -0
  373. package/dist/cli/statuses.js.map +1 -0
  374. package/dist/cli/version.d.ts +8 -0
  375. package/dist/cli/version.d.ts.map +1 -1
  376. package/dist/cli/version.js +32 -1
  377. package/dist/cli/version.js.map +1 -1
  378. package/dist/cli-api.d.ts +33 -15
  379. package/dist/cli-api.d.ts.map +1 -1
  380. package/dist/cli-api.js +31 -11
  381. package/dist/cli-api.js.map +1 -1
  382. package/dist/composition/bridge-analysis.d.ts.map +1 -1
  383. package/dist/composition/bridge-analysis.js +2 -1
  384. package/dist/composition/bridge-analysis.js.map +1 -1
  385. package/dist/composition/canonical-compare.d.ts +36 -11
  386. package/dist/composition/canonical-compare.d.ts.map +1 -1
  387. package/dist/composition/canonical-compare.js +424 -56
  388. package/dist/composition/canonical-compare.js.map +1 -1
  389. package/dist/composition/canonical-graph.d.ts +2 -2
  390. package/dist/composition/canonical-graph.js +3 -3
  391. package/dist/composition/canonical-graph.js.map +1 -1
  392. package/dist/composition/canonical-prefactors.d.ts +24 -1
  393. package/dist/composition/canonical-prefactors.d.ts.map +1 -1
  394. package/dist/composition/canonical-prefactors.js +97 -1
  395. package/dist/composition/canonical-prefactors.js.map +1 -1
  396. package/dist/composition/compose-symbolic.js +1 -1
  397. package/dist/composition/compose-symbolic.js.map +1 -1
  398. package/dist/composition/compose.d.ts.map +1 -1
  399. package/dist/composition/compose.js +17 -9
  400. package/dist/composition/compose.js.map +1 -1
  401. package/dist/composition/composition-recovery.d.ts +47 -0
  402. package/dist/composition/composition-recovery.d.ts.map +1 -0
  403. package/dist/composition/composition-recovery.js +77 -0
  404. package/dist/composition/composition-recovery.js.map +1 -0
  405. package/dist/composition/consequence.d.ts +39 -0
  406. package/dist/composition/consequence.d.ts.map +1 -1
  407. package/dist/composition/consequence.js +37 -0
  408. package/dist/composition/consequence.js.map +1 -1
  409. package/dist/composition/discovery.d.ts +20 -0
  410. package/dist/composition/discovery.d.ts.map +1 -1
  411. package/dist/composition/discovery.js +27 -5
  412. package/dist/composition/discovery.js.map +1 -1
  413. package/dist/composition/edge.d.ts +1 -1
  414. package/dist/composition/edge.d.ts.map +1 -1
  415. package/dist/composition/edge.js.map +1 -1
  416. package/dist/composition/edges/_catalog-helpers.d.ts +4 -0
  417. package/dist/composition/edges/_catalog-helpers.d.ts.map +1 -1
  418. package/dist/composition/edges/_catalog-helpers.js +15 -0
  419. package/dist/composition/edges/_catalog-helpers.js.map +1 -1
  420. package/dist/composition/edges/calibration.d.ts.map +1 -1
  421. package/dist/composition/edges/calibration.js +57 -0
  422. package/dist/composition/edges/calibration.js.map +1 -1
  423. package/dist/composition/edges/catalog-fields.d.ts.map +1 -1
  424. package/dist/composition/edges/catalog-fields.js +2 -1
  425. package/dist/composition/edges/catalog-fields.js.map +1 -1
  426. package/dist/composition/edges/catalog-gravitation-cosmology.d.ts.map +1 -1
  427. package/dist/composition/edges/catalog-gravitation-cosmology.js +2 -1
  428. package/dist/composition/edges/catalog-gravitation-cosmology.js.map +1 -1
  429. package/dist/composition/edges/catalog-quantum.d.ts.map +1 -1
  430. package/dist/composition/edges/catalog-quantum.js +26 -0
  431. package/dist/composition/edges/catalog-quantum.js.map +1 -1
  432. package/dist/composition/edges/catalog-tranche.d.ts.map +1 -1
  433. package/dist/composition/edges/catalog-tranche.js +2 -1
  434. package/dist/composition/edges/catalog-tranche.js.map +1 -1
  435. package/dist/composition/expr-eval.d.ts.map +1 -1
  436. package/dist/composition/expr-eval.js +4 -1
  437. package/dist/composition/expr-eval.js.map +1 -1
  438. package/dist/composition/expr-simplify.js +1 -1
  439. package/dist/composition/expr-simplify.js.map +1 -1
  440. package/dist/composition/frontier-account.d.ts +78 -0
  441. package/dist/composition/frontier-account.d.ts.map +1 -0
  442. package/dist/composition/frontier-account.js +127 -0
  443. package/dist/composition/frontier-account.js.map +1 -0
  444. package/dist/composition/graph-viz.d.ts +7 -22
  445. package/dist/composition/graph-viz.d.ts.map +1 -1
  446. package/dist/composition/graph-viz.js +4 -27
  447. package/dist/composition/graph-viz.js.map +1 -1
  448. package/dist/composition/grounding.d.ts +49 -0
  449. package/dist/composition/grounding.d.ts.map +1 -1
  450. package/dist/composition/grounding.js +38 -0
  451. package/dist/composition/grounding.js.map +1 -1
  452. package/dist/composition/index.d.ts +0 -2
  453. package/dist/composition/index.d.ts.map +1 -1
  454. package/dist/composition/index.js +1 -1
  455. package/dist/composition/index.js.map +1 -1
  456. package/dist/composition/probe/expression-gaps.d.ts +27 -0
  457. package/dist/composition/probe/expression-gaps.d.ts.map +1 -0
  458. package/dist/composition/probe/expression-gaps.js +47 -0
  459. package/dist/composition/probe/expression-gaps.js.map +1 -0
  460. package/dist/composition/probe/frontier.d.ts +2 -1
  461. package/dist/composition/probe/frontier.d.ts.map +1 -1
  462. package/dist/composition/probe/frontier.js +3 -2
  463. package/dist/composition/probe/frontier.js.map +1 -1
  464. package/dist/composition/probe/index.d.ts +4 -1
  465. package/dist/composition/probe/index.d.ts.map +1 -1
  466. package/dist/composition/probe/index.js +3 -1
  467. package/dist/composition/probe/index.js.map +1 -1
  468. package/dist/composition/probe/pipeline.d.ts +2 -0
  469. package/dist/composition/probe/pipeline.d.ts.map +1 -1
  470. package/dist/composition/probe/pipeline.js +6 -2
  471. package/dist/composition/probe/pipeline.js.map +1 -1
  472. package/dist/composition/probe/problem.d.ts +7 -0
  473. package/dist/composition/probe/problem.d.ts.map +1 -1
  474. package/dist/composition/probe/problem.js +15 -5
  475. package/dist/composition/probe/problem.js.map +1 -1
  476. package/dist/composition/probe/search-budget.d.ts.map +1 -1
  477. package/dist/composition/probe/search-budget.js +6 -2
  478. package/dist/composition/probe/search-budget.js.map +1 -1
  479. package/dist/composition/probe/study.d.ts +340 -0
  480. package/dist/composition/probe/study.d.ts.map +1 -0
  481. package/dist/composition/probe/study.js +1519 -0
  482. package/dist/composition/probe/study.js.map +1 -0
  483. package/dist/composition/proposed-bridges.js +1 -1
  484. package/dist/composition/proposed-bridges.js.map +1 -1
  485. package/dist/composition/quantities.d.ts +4 -16
  486. package/dist/composition/quantities.d.ts.map +1 -1
  487. package/dist/composition/quantities.js +4 -16
  488. package/dist/composition/quantities.js.map +1 -1
  489. package/dist/composition/retrodiction.d.ts.map +1 -1
  490. package/dist/composition/retrodiction.js +6 -2
  491. package/dist/composition/retrodiction.js.map +1 -1
  492. package/dist/composition/uncertainty.d.ts +1 -1
  493. package/dist/composition/uncertainty.d.ts.map +1 -1
  494. package/dist/composition/user-equation.d.ts +87 -14
  495. package/dist/composition/user-equation.d.ts.map +1 -1
  496. package/dist/composition/user-equation.js +266 -59
  497. package/dist/composition/user-equation.js.map +1 -1
  498. package/dist/core/constants.d.ts +9 -4
  499. package/dist/core/constants.d.ts.map +1 -1
  500. package/dist/core/constants.js +9 -4
  501. package/dist/core/constants.js.map +1 -1
  502. package/dist/core/types.d.ts +1 -1
  503. package/dist/core/types.d.ts.map +1 -1
  504. package/dist/core/types.js +2 -1
  505. package/dist/core/types.js.map +1 -1
  506. package/dist/dimensional/curvature.d.ts +7 -56
  507. package/dist/dimensional/curvature.d.ts.map +1 -1
  508. package/dist/dimensional/curvature.js +7 -76
  509. package/dist/dimensional/curvature.js.map +1 -1
  510. package/dist/dimensional/dimension-spec.d.ts +7 -1
  511. package/dist/dimensional/dimension-spec.d.ts.map +1 -1
  512. package/dist/dimensional/dimension-spec.js +131 -3
  513. package/dist/dimensional/dimension-spec.js.map +1 -1
  514. package/dist/dimensional/formula-names.d.ts +30 -0
  515. package/dist/dimensional/formula-names.d.ts.map +1 -0
  516. package/dist/dimensional/formula-names.js +37 -0
  517. package/dist/dimensional/formula-names.js.map +1 -0
  518. package/dist/dimensional/natural-units.d.ts +33 -0
  519. package/dist/dimensional/natural-units.d.ts.map +1 -0
  520. package/dist/dimensional/natural-units.js +58 -0
  521. package/dist/dimensional/natural-units.js.map +1 -0
  522. package/dist/{composition → dimensional}/symbolic-constants.d.ts +21 -2
  523. package/dist/dimensional/symbolic-constants.d.ts.map +1 -0
  524. package/dist/dimensional/symbolic-constants.js +116 -0
  525. package/dist/dimensional/symbolic-constants.js.map +1 -0
  526. package/dist/dimensional/unit-convention.d.ts +30 -0
  527. package/dist/dimensional/unit-convention.d.ts.map +1 -0
  528. package/dist/dimensional/unit-convention.js +60 -0
  529. package/dist/dimensional/unit-convention.js.map +1 -0
  530. package/dist/dimensional/units.d.ts +43 -0
  531. package/dist/dimensional/units.d.ts.map +1 -0
  532. package/dist/dimensional/units.js +197 -0
  533. package/dist/dimensional/units.js.map +1 -0
  534. package/dist/index.d.ts +8 -4
  535. package/dist/index.d.ts.map +1 -1
  536. package/dist/index.js +7 -3
  537. package/dist/index.js.map +1 -1
  538. package/dist/numerical/bianchi-residual.d.ts +55 -0
  539. package/dist/numerical/bianchi-residual.d.ts.map +1 -0
  540. package/dist/numerical/bianchi-residual.js +79 -0
  541. package/dist/numerical/bianchi-residual.js.map +1 -0
  542. package/dist/numerical/binding-value.d.ts +67 -0
  543. package/dist/numerical/binding-value.d.ts.map +1 -0
  544. package/dist/numerical/binding-value.js +347 -0
  545. package/dist/numerical/binding-value.js.map +1 -0
  546. package/dist/numerical/connection-lowering-helpers.d.ts.map +1 -1
  547. package/dist/numerical/connection-lowering-helpers.js +13 -26
  548. package/dist/numerical/connection-lowering-helpers.js.map +1 -1
  549. package/dist/numerical/curvature-lowering-helpers.d.ts.map +1 -1
  550. package/dist/numerical/curvature-lowering-helpers.js +9 -0
  551. package/dist/numerical/curvature-lowering-helpers.js.map +1 -1
  552. package/dist/numerical/float64-engine.d.ts.map +1 -1
  553. package/dist/numerical/float64-engine.js +23 -16
  554. package/dist/numerical/float64-engine.js.map +1 -1
  555. package/dist/numerical/formula-dimension.d.ts +7 -0
  556. package/dist/numerical/formula-dimension.d.ts.map +1 -1
  557. package/dist/numerical/formula-dimension.js +23 -6
  558. package/dist/numerical/formula-dimension.js.map +1 -1
  559. package/dist/numerical/formula-mathts.d.ts.map +1 -1
  560. package/dist/numerical/formula-mathts.js +68 -6
  561. package/dist/numerical/formula-mathts.js.map +1 -1
  562. package/dist/numerical/formula.d.ts +27 -0
  563. package/dist/numerical/formula.d.ts.map +1 -1
  564. package/dist/numerical/formula.js +68 -6
  565. package/dist/numerical/formula.js.map +1 -1
  566. package/dist/numerical/spacetime-metrics.d.ts +243 -0
  567. package/dist/numerical/spacetime-metrics.d.ts.map +1 -0
  568. package/dist/numerical/spacetime-metrics.js +1056 -0
  569. package/dist/numerical/spacetime-metrics.js.map +1 -0
  570. package/dist/relations/composition-table.d.ts +61 -0
  571. package/dist/relations/composition-table.d.ts.map +1 -0
  572. package/dist/relations/composition-table.js +140 -0
  573. package/dist/relations/composition-table.js.map +1 -0
  574. package/dist/relations/conventions.d.ts +63 -0
  575. package/dist/relations/conventions.d.ts.map +1 -0
  576. package/dist/relations/conventions.js +93 -0
  577. package/dist/relations/conventions.js.map +1 -0
  578. package/dist/relations/regime.d.ts +159 -0
  579. package/dist/relations/regime.d.ts.map +1 -0
  580. package/dist/relations/regime.js +304 -0
  581. package/dist/relations/regime.js.map +1 -0
  582. package/dist/relations/types.d.ts +259 -0
  583. package/dist/relations/types.d.ts.map +1 -0
  584. package/dist/relations/types.js +37 -0
  585. package/dist/relations/types.js.map +1 -0
  586. package/package.json +166 -163
  587. package/dist/composition/poster-source.d.ts.map +0 -1
  588. package/dist/composition/poster-source.js.map +0 -1
  589. package/dist/composition/symbolic-constants.d.ts.map +0 -1
  590. package/dist/composition/symbolic-constants.js +0 -65
  591. package/dist/composition/symbolic-constants.js.map +0 -1
@@ -24,11 +24,14 @@
24
24
  */
25
25
  import { equals } from '../dimensional/algebra.js';
26
26
  import { CANONICAL_EQUATIONS } from '../canonical/registry.js';
27
- import { CONSTANTS } from './symbolic-constants.js';
27
+ import { CONSTANTS, piMultipleValue } from '../dimensional/symbolic-constants.js';
28
28
  import { evalExpr } from './expr-eval.js';
29
- import { canonicalPrefactor } from './canonical-prefactors.js';
29
+ import { CANONICAL_GROUP_PREFACTORS, canonicalPrefactor } from './canonical-prefactors.js';
30
+ import { formulaNameDimensions } from '../dimensional/formula-names.js';
30
31
  import { parseUserEquation, resolveToCatalogName } from './user-equation.js';
31
- import { parsePhysics } from '../numerical/formula-registry.js';
32
+ import { getFormulaParser, parsePhysics } from '../numerical/formula-registry.js';
33
+ import { formulaSymbolDimension } from '../numerical/formula-dimension.js';
34
+ import { CATALOG_GRAPH } from './catalog-graph.js';
32
35
  import { DIMENSIONLESS } from '../dimensional/types.js';
33
36
  /**
34
37
  * The comparison points: variable `i` (in sorted name order) takes the value
@@ -42,18 +45,133 @@ import { DIMENSIONLESS } from '../dimensional/types.js';
42
45
  const FIXED_POINT_EXPONENTS = [1, 1.3, 1.6];
43
46
  /** Relative tolerance for "the ratio is constant" and "the ratio is 1". @internal */
44
47
  const RATIO_TOLERANCE = 1e-9;
48
+ /**
49
+ * Catalog names for an entry whose frozen target name is a different word.
50
+ * CE-schwarzschild-radius's L0 record calls the target `radius`; the catalog
51
+ * quantity, and the name a student writes, is `schwarzschild-radius`.
52
+ */
53
+ const ENTRY_TARGET_ALIASES = {
54
+ 'CE-schwarzschild-radius': ['schwarzschild-radius'],
55
+ // The L0 id keeps the catalog name. The reduced name is the same entry.
56
+ // The non-reduced entry also answers to that catalog name when the formula uses h.
57
+ 'CE-compton-wavelength': ['reduced-compton-wavelength'],
58
+ 'CE-compton-wavelength-full': ['compton-wavelength'],
59
+ };
60
+ /** What a dimensionless registry stub stands for, when the symbol is not the latex. */
61
+ const STUB_GLOSS = {
62
+ one_minus_e_sq: '1-e²',
63
+ };
45
64
  const normalize = (name) => name.replace(/_/g, '-');
65
+ /**
66
+ * Pair each user source with one canonical variable: by name first, then by a dimension that
67
+ * exactly one remaining canonical variable carries, repeated until nothing changes. `null` when the
68
+ * sources cannot be this entry's variables (a count, a name without a dimension, or a dimension no
69
+ * variable left carries); `'ambiguous'` when every source has a same-dimension partner but the
70
+ * pairing is not unique. Returns user name → canonical name, both normalized.
71
+ */
72
+ function pairSources(sources, variables) {
73
+ if (sources.length !== variables.length)
74
+ return null;
75
+ const pairs = new Map();
76
+ const freeVars = new Map(variables.map((v) => [normalize(v.name), v.dim]));
77
+ let open = sources.filter((s) => {
78
+ if (!freeVars.has(s.name))
79
+ return true;
80
+ pairs.set(s.name, s.name);
81
+ freeVars.delete(s.name);
82
+ return false;
83
+ });
84
+ let progress = true;
85
+ while (open.length > 0 && progress) {
86
+ progress = false;
87
+ for (const s of open) {
88
+ if (s.dim === undefined)
89
+ return null;
90
+ const partners = [...freeVars].filter(([, dim]) => equals(dim, s.dim));
91
+ if (partners.length === 0)
92
+ return null;
93
+ if (partners.length === 1) {
94
+ pairs.set(s.name, partners[0][0]);
95
+ freeVars.delete(partners[0][0]);
96
+ progress = true;
97
+ }
98
+ }
99
+ open = open.filter((s) => !pairs.has(s.name));
100
+ }
101
+ return open.length === 0 ? pairs : 'ambiguous';
102
+ }
103
+ /**
104
+ * Peel user sources that restate a CE governing *constant* (persona finding W1).
105
+ *
106
+ * CE-mass-energy lists `c` as governing, but `c` is in {@link CONSTANTS}, so it is not a free
107
+ * variable of the comparison. Writing the catalog quantity `speed-of-light` (same dimension) must
108
+ * not make the source set look larger than `{mass}` and skip the prefactor check. A source pairs
109
+ * with a constant by name, or by a dimension that exactly one remaining constant carries and that
110
+ * no free variable carries (variables win — `velocity` still pairs with CE-kinetic-energy's
111
+ * `speed`). Returns the sources left for {@link pairSources}, plus user→constant name pairs.
112
+ * Leftover sources that match no variable and no unique constant make the entry a non-match
113
+ * (`null` from the caller when `forVariables` then fails to pair).
114
+ */
115
+ function peelConstantAliases(sources, variables, constants) {
116
+ const constPairs = new Map();
117
+ const freeConsts = new Map(constants.map((c) => [normalize(c.name), c.dim]));
118
+ const forVariables = [];
119
+ for (const s of sources) {
120
+ if (variables.some((v) => normalize(v.name) === s.name)) {
121
+ forVariables.push(s);
122
+ continue;
123
+ }
124
+ if (freeConsts.has(s.name)) {
125
+ constPairs.set(s.name, s.name);
126
+ freeConsts.delete(s.name);
127
+ continue;
128
+ }
129
+ if (s.dim !== undefined) {
130
+ const varHits = variables.filter((v) => equals(v.dim, s.dim));
131
+ if (varHits.length > 0) {
132
+ forVariables.push(s);
133
+ continue;
134
+ }
135
+ // h and ħ are both action. A formula that writes one is not the other.
136
+ if (Object.prototype.hasOwnProperty.call(CONSTANTS, s.name)) {
137
+ forVariables.push(s);
138
+ continue;
139
+ }
140
+ const constHits = [...freeConsts].filter(([, dim]) => equals(dim, s.dim));
141
+ if (constHits.length === 1) {
142
+ constPairs.set(s.name, constHits[0][0]);
143
+ freeConsts.delete(constHits[0][0]);
144
+ continue;
145
+ }
146
+ }
147
+ forVariables.push(s);
148
+ }
149
+ return { forVariables, constPairs };
150
+ }
46
151
  /** A governing variable that is a registered physical constant of the same dimension. */
47
152
  function isConstant(v) {
48
153
  const c = CONSTANTS[v.name];
49
154
  return c !== undefined && equals(c.dim, v.dim);
50
155
  }
156
+ /**
157
+ * The catalog bridge through which `wantTarget` names this entry's target: the entry records that
158
+ * it restates that bridge (`restatesBridge`), and the bridge's graph edge has `wantTarget` as its
159
+ * target (persona finding W7: `landauer-erasure-energy` is BE-16's target, and CE-landauer, which
160
+ * restates BE-16, names it `erasure-energy`). A recorded restatement, never a shared dimension.
161
+ */
162
+ function targetThroughRestatedBridge(entry, wantTarget) {
163
+ if (entry.restatesBridge === undefined)
164
+ return undefined;
165
+ const beId = Number(entry.restatesBridge);
166
+ return CATALOG_GRAPH.find((e) => e.beId === beId && normalize(e.target.name) === wantTarget)?.id;
167
+ }
51
168
  /** The free (non-constant, non-literal) symbols of an AST, with their dimensions. */
52
169
  function freeSymbols(node, out) {
53
170
  if (node.kind === 'symbol') {
54
171
  const literal = Number.isFinite(Number(node.name));
55
- if (!literal && CONSTANTS[node.name] === undefined)
172
+ if (!literal && CONSTANTS[node.name] === undefined && piMultipleValue(node.name) === undefined) {
56
173
  out.set(node.name, node.dim);
174
+ }
57
175
  return out;
58
176
  }
59
177
  const args = node.args ?? [];
@@ -62,12 +180,31 @@ function freeSymbols(node, out) {
62
180
  return out;
63
181
  }
64
182
  /**
65
- * Map each free AST symbol to a governing variable: by name first, then by a
66
- * dimension that exactly one unassigned variable carries. `null` when that fails.
183
+ * Dimensionless symbols the entry's AST holds that its governing set does not, and that the user
184
+ * names too: CE-ideal-gas writes `P = N k_B T/V` with the count `N` in its AST only (persona finding
185
+ * L6). They join the comparison variables BY NAME only; pairing a dimensionless stub such as
186
+ * `one_minus_e_sq` with any dimensionless user quantity by dimension would compare different laws.
187
+ */
188
+ function astOnlyCounts(entry, userNames) {
189
+ if (entry.scalarAst === undefined)
190
+ return [];
191
+ const governing = new Set(entry.dimensional.governing.map((g) => normalize(g.name)));
192
+ return [...freeSymbols(entry.scalarAst, new Map())]
193
+ .filter(([name, dim]) => /^[A-Za-z][A-Za-z0-9_]*$/.test(name) && equals(dim, DIMENSIONLESS))
194
+ .filter(([name]) => !governing.has(normalize(name)) && userNames.has(normalize(name)))
195
+ .map(([name, dim]) => ({ name, dim }));
196
+ }
197
+ /**
198
+ * Every way to map free AST symbols onto governing variables: by name first,
199
+ * then any bijection that respects dimension. One map when each remaining
200
+ * symbol has a unique dimension; several when a product such as m₁ m₂ can be
201
+ * assigned either way. Empty when the counts differ or a symbol has no
202
+ * variable of its dimension. More than 24 bijections is treated as empty —
203
+ * that pairing is not checked, rather than searched.
67
204
  */
68
- function alignSymbols(symbols, governing) {
205
+ function symbolAlignments(symbols, governing) {
69
206
  if (symbols.size !== governing.length)
70
- return null;
207
+ return [];
71
208
  const assignment = new Map();
72
209
  const free = new Set(governing.map((g) => g.name));
73
210
  for (const s of [...symbols.keys()].sort()) {
@@ -76,16 +213,58 @@ function alignSymbols(symbols, governing) {
76
213
  free.delete(s);
77
214
  }
78
215
  }
79
- for (const [s, dim] of [...symbols.entries()].sort(([a], [b]) => a.localeCompare(b))) {
80
- if (assignment.has(s))
81
- continue;
82
- const candidates = governing.filter((g) => free.has(g.name) && equals(g.dim, dim));
83
- if (candidates.length !== 1)
84
- return null;
85
- assignment.set(s, candidates[0].name);
86
- free.delete(candidates[0].name);
216
+ const rest = [...symbols.entries()]
217
+ .filter(([s]) => !assignment.has(s))
218
+ .sort(([a], [b]) => a.localeCompare(b));
219
+ const out = [];
220
+ const CAP = 24;
221
+ const rec = (i) => {
222
+ if (out.length > CAP)
223
+ return;
224
+ if (i === rest.length) {
225
+ out.push(new Map(assignment));
226
+ return;
227
+ }
228
+ const [s, dim] = rest[i];
229
+ const candidates = governing
230
+ .filter((g) => free.has(g.name) && equals(g.dim, dim))
231
+ .map((g) => g.name)
232
+ .sort();
233
+ for (const c of candidates) {
234
+ assignment.set(s, c);
235
+ free.delete(c);
236
+ rec(i + 1);
237
+ free.add(c);
238
+ assignment.delete(s);
239
+ if (out.length > CAP)
240
+ return;
241
+ }
242
+ };
243
+ rec(0);
244
+ return out.length > CAP ? [] : out;
245
+ }
246
+ /** Why an AST could not be aligned, naming a dimensionless stub the user did not. */
247
+ function alignmentDetail(symbols, variables) {
248
+ const named = new Set(variables.map((v) => v.name));
249
+ const stubs = [...symbols.entries()]
250
+ .filter(([name, dim]) => !named.has(name) && equals(dim, DIMENSIONLESS))
251
+ .map(([name]) => name)
252
+ .sort();
253
+ if (symbols.size !== variables.length && stubs.length > 0) {
254
+ const shown = stubs.map((s) => (STUB_GLOSS[s] === undefined ? s : `${s} (${STUB_GLOSS[s]})`));
255
+ return `its formula depends on ${shown.join(', ')}, which your formula does not name`;
87
256
  }
88
- return assignment;
257
+ return 'its variables could not be aligned by name or by a unique dimension';
258
+ }
259
+ /** True when every alignment produced the same ratio at each fixed point. */
260
+ function sameRatios(series) {
261
+ const first = series[0];
262
+ if (first === undefined)
263
+ return false;
264
+ return series.every((s) => s.every((r, i) => {
265
+ const r0 = first[i];
266
+ return Number.isFinite(r) && Number.isFinite(r0) && r0 !== 0 && Math.abs(r / r0 - 1) <= RATIO_TOLERANCE;
267
+ }));
89
268
  }
90
269
  function classify(entry, ratios, recordsPrefactor) {
91
270
  const base = { id: entry.id, name: entry.name };
@@ -99,7 +278,11 @@ function classify(entry, ratios, recordsPrefactor) {
99
278
  kind: 'prefactor-unchecked',
100
279
  detail: entry.epistemicStatus === 'dimensional'
101
280
  ? 'the registry records its dimensional form only'
102
- : 'the registry records it only up to a constant',
281
+ : entry.epistemicStatus === 'fully-quantitative' && entry.fieldEquation !== undefined
282
+ ? 'the registry records its prefactor only in its field equation, and its scalar record is the dimensional monomial'
283
+ : entry.epistemicStatus === 'fully-quantitative'
284
+ ? 'its scalar record is the dimensional monomial only'
285
+ : 'the registry records it only up to a constant',
103
286
  };
104
287
  }
105
288
  return Math.abs(r0 - 1) <= RATIO_TOLERANCE
@@ -108,55 +291,192 @@ function classify(entry, ratios, recordsPrefactor) {
108
291
  }
109
292
  /**
110
293
  * Compare a user formula with every canonical equation that has the same
111
- * target and the same non-constant variables (names match after `_` → `-`).
112
- * `evaluateUser` receives values keyed by the CANONICAL variable names.
294
+ * target and the same non-constant variables. The target must match by name
295
+ * (after `_` → `-`): pairing it by dimension would reach every law of that
296
+ * dimension. Each source matches a variable by name, or, when the source
297
+ * carries a dimension, by a dimension exactly one remaining variable carries
298
+ * (`velocity` → CE-kinetic-energy's `speed`); such pairs are listed in
299
+ * `paired`. A non-unique pairing is reported as `not-compared`, never guessed.
300
+ * `evaluateUser` receives values keyed by the user's (normalized) source names.
113
301
  * Returns one comparison per matching entry, in registry order; empty when
114
302
  * no entry matches.
115
303
  *
116
304
  * @internal
117
305
  */
118
- export function compareWithCanonical(target, sources, evaluateUser, entries = CANONICAL_EQUATIONS) {
306
+ function overrideValue(name, si, overrides) {
307
+ if (overrides !== undefined && Object.prototype.hasOwnProperty.call(overrides, name))
308
+ return overrides[name];
309
+ return si;
310
+ }
311
+ /** A short label for a non-SI constant table, or undefined when the table is SI. */
312
+ function overrideLabel(overrides) {
313
+ if (overrides === undefined)
314
+ return undefined;
315
+ const bits = [];
316
+ if (overrides.c === 1)
317
+ bits.push('c = 1');
318
+ if (overrides.hbar === 1)
319
+ bits.push('ħ = 1');
320
+ if (overrides.h === 2 * Math.PI)
321
+ bits.push('h = 2π');
322
+ if (overrides.G === 1)
323
+ bits.push('G = 1');
324
+ return bits.length === 0 ? undefined : bits.join(', ');
325
+ }
326
+ export function compareWithCanonical(target, sources, evaluateUser, entries = CANONICAL_EQUATIONS, constantOverrides) {
119
327
  const wantTarget = normalize(target);
120
- const wantSources = [...new Set(sources.map(normalize))].sort();
328
+ const wantSources = new Map();
329
+ for (const s of sources) {
330
+ const name = normalize(typeof s === 'string' ? s : s.name);
331
+ if (!wantSources.has(name))
332
+ wantSources.set(name, typeof s === 'string' ? { name } : { name, dim: s.dim });
333
+ }
121
334
  const results = [];
122
335
  for (const entry of entries) {
123
336
  const d = entry.dimensional;
124
- if (normalize(d.target.name) !== wantTarget)
337
+ const via = normalize(d.target.name) === wantTarget ? undefined : targetThroughRestatedBridge(entry, wantTarget);
338
+ const alias = (ENTRY_TARGET_ALIASES[entry.id] ?? []).includes(wantTarget);
339
+ if (normalize(d.target.name) !== wantTarget && via === undefined && !alias)
125
340
  continue;
126
- const variables = d.governing.filter((g) => !isConstant(g));
127
- const names = variables.map((g) => normalize(g.name)).sort();
128
- if (names.length !== wantSources.length || names.some((n, i) => n !== wantSources[i]))
341
+ const targetVia = via === undefined ? {} : { targetVia: { bridge: via, its: d.target.name } };
342
+ let variables = d.governing.filter((g) => !isConstant(g));
343
+ const constants = d.governing.filter(isConstant);
344
+ // W1: sources that restate a governing constant (speed-of-light ↔ c) peel off first so they
345
+ // do not inflate the free-variable count and skip the prefactor check.
346
+ const { forVariables, constPairs } = peelConstantAliases([...wantSources.values()], variables, constants);
347
+ // A dimensionless group the record does not carry (sound-speed γ) is checked only when the
348
+ // user wrote it. Friedmann's curvature term is CE-friedmann-curvature, not an extension of the flat entry.
349
+ const groupSpec = CANONICAL_GROUP_PREFACTORS.find((g) => g.id === entry.id);
350
+ let boundGroup;
351
+ if (groupSpec) {
352
+ const idx = forVariables.findIndex((s) => s.name === groupSpec.group);
353
+ if (idx >= 0) {
354
+ boundGroup = forVariables[idx].name;
355
+ forVariables.splice(idx, 1);
356
+ }
357
+ }
358
+ let pairing = pairSources(forVariables, variables);
359
+ if (pairing === null) {
360
+ // L6: a count the AST holds but the governing set does not (CE-ideal-gas's N), named by the user.
361
+ const counts = astOnlyCounts(entry, new Set(forVariables.map((s) => s.name)));
362
+ if (counts.length > 0) {
363
+ const widened = [...variables, ...counts];
364
+ pairing = pairSources(forVariables, widened);
365
+ if (pairing !== null)
366
+ variables = widened;
367
+ }
368
+ }
369
+ if (pairing === null)
129
370
  continue;
130
- const points = FIXED_POINT_EXPONENTS.map((p) => Object.fromEntries(names.map((n, i) => [n, Math.pow(1.7 + i, p)])));
371
+ if (pairing === 'ambiguous') {
372
+ results.push({
373
+ id: entry.id,
374
+ name: entry.name,
375
+ kind: 'not-compared',
376
+ detail: 'your variable names differ from its names, and they pair with its variables by dimension in more than one way',
377
+ ...targetVia,
378
+ });
379
+ continue;
380
+ }
381
+ const byDimension = [...pairing, ...constPairs]
382
+ .filter(([u, c]) => u !== c)
383
+ .sort(([a], [b]) => a.localeCompare(b));
384
+ const paired = byDimension.length > 0 ? { paired: byDimension } : {};
385
+ const names = variables.map((g) => normalize(g.name)).sort();
386
+ const points = FIXED_POINT_EXPONENTS.map((p) => {
387
+ const row = Object.fromEntries(names.map((n, i) => [n, Math.pow(1.7 + i, p)]));
388
+ if (boundGroup !== undefined)
389
+ row['__group'] = Math.pow(2.3, p);
390
+ return row;
391
+ });
392
+ // Constant aliases bind to the registered SI value (same as the canonical AST's CONSTANTS
393
+ // lookup), not to a fixed-point sample — otherwise the ratio would wander with the points.
394
+ const constBindings = Object.fromEntries([...constPairs].map(([u, cName]) => {
395
+ const c = CONSTANTS[cName];
396
+ if (c === undefined) {
397
+ throw new Error(`compareWithCanonical: governing constant '${cName}' is not in CONSTANTS`);
398
+ }
399
+ return [u, overrideValue(cName, c.value, constantOverrides)];
400
+ }));
401
+ const userAt = (p) => evaluateUser({
402
+ ...Object.fromEntries([...pairing].map(([u, c]) => [u, p[c]])),
403
+ ...constBindings,
404
+ ...(boundGroup === undefined ? {} : { [boundGroup]: p['__group'] }),
405
+ });
131
406
  // A prefactor the entry does not record may come from the sourced table,
132
407
  // which lives outside the pinned src/canonical tree.
133
408
  const tabled = entry.epistemicStatus === 'fully-quantitative' ? undefined : canonicalPrefactor(entry.id);
134
- const factor = tabled ?? 1;
409
+ const extraFactor = (p) => boundGroup === undefined || groupSpec === undefined
410
+ ? 1
411
+ : groupSpec.coefficient * Math.pow(p['__group'], groupSpec.exponent);
412
+ const scale = (flat, p) => (tabled ?? 1) * extraFactor(p) * flat;
135
413
  let canonicalAt;
136
414
  if (entry.scalarAst !== undefined) {
137
- const alignment = alignSymbols(freeSymbols(entry.scalarAst, new Map()), variables);
138
- if (alignment === null) {
415
+ const ast = entry.scalarAst;
416
+ const symbols = freeSymbols(ast, new Map());
417
+ const alignments = symbolAlignments(symbols, variables);
418
+ const at = (alignment) => (p) => scale(evalExpr(ast, {
419
+ ...(constantOverrides ?? {}),
420
+ ...Object.fromEntries([...alignment].map(([sym, g]) => [sym, p[normalize(g)]])),
421
+ }), p);
422
+ if (alignments.length === 0) {
139
423
  results.push({
140
424
  id: entry.id,
141
425
  name: entry.name,
142
426
  kind: 'not-compared',
143
- detail: 'its variables could not be aligned by name or by a unique dimension',
427
+ detail: alignmentDetail(symbols, variables),
428
+ ...paired, ...targetVia,
144
429
  });
145
430
  continue;
146
431
  }
147
- const ast = entry.scalarAst;
148
- canonicalAt = (p) => factor * evalExpr(ast, Object.fromEntries([...alignment].map(([sym, g]) => [sym, p[normalize(g)]])));
432
+ if (alignments.length === 1) {
433
+ const alignment = alignments[0];
434
+ canonicalAt = at(alignment);
435
+ }
436
+ else {
437
+ let series;
438
+ try {
439
+ series = alignments.map((alignment) => points.map((p) => userAt(p) / at(alignment)(p)));
440
+ }
441
+ catch (e) {
442
+ results.push({
443
+ id: entry.id,
444
+ name: entry.name,
445
+ kind: 'not-compared',
446
+ detail: `an evaluation failed (${e instanceof Error ? e.message : String(e)})`,
447
+ ...paired, ...targetVia,
448
+ });
449
+ continue;
450
+ }
451
+ if (!sameRatios(series)) {
452
+ results.push({
453
+ id: entry.id,
454
+ name: entry.name,
455
+ kind: 'not-compared',
456
+ detail: 'swapping its same-dimension symbols changes the ratio, so they were not paired',
457
+ ...paired, ...targetVia,
458
+ });
459
+ continue;
460
+ }
461
+ // The ratio does not depend on which same-dimension symbol takes which
462
+ // variable (m₁ m₂ = m₂ m₁). One assignment is enough; none is named.
463
+ canonicalAt = at(alignments[0]);
464
+ }
149
465
  }
150
466
  else if (d.monomial !== null) {
467
+ // W4: a governing constant takes its SI value, as on the user side and in the AST branch. A
468
+ // name that is neither a variable nor a constant has no value, so the ratio is not finite and
469
+ // the entry is reported as not compared; reading it as 1 made Kepler III "factor 122404".
151
470
  const monomial = d.monomial;
152
- canonicalAt = (p) => factor * Object.entries(monomial).reduce((acc, [n, e]) => acc * Math.pow(p[normalize(n)] ?? 1, e), 1);
471
+ const constValues = new Map(constants.map((g) => [normalize(g.name), overrideValue(g.name, CONSTANTS[g.name].value, constantOverrides)]));
472
+ canonicalAt = (p) => scale(Object.entries(monomial).reduce((acc, [n, e]) => acc * Math.pow(p[normalize(n)] ?? constValues.get(normalize(n)) ?? Number.NaN, e), 1), p);
153
473
  }
154
474
  else {
155
475
  continue;
156
476
  }
157
477
  let ratios;
158
478
  try {
159
- ratios = points.map((p) => evaluateUser(p) / canonicalAt(p));
479
+ ratios = points.map((p) => userAt(p) / canonicalAt(p));
160
480
  }
161
481
  catch (e) {
162
482
  results.push({
@@ -164,47 +484,87 @@ export function compareWithCanonical(target, sources, evaluateUser, entries = CA
164
484
  name: entry.name,
165
485
  kind: 'not-compared',
166
486
  detail: `an evaluation failed (${e instanceof Error ? e.message : String(e)})`,
487
+ ...paired, ...targetVia,
167
488
  });
168
489
  continue;
169
490
  }
170
491
  if (!ratios.every((r) => Number.isFinite(r) && r !== 0)) {
171
- results.push({ id: entry.id, name: entry.name, kind: 'not-compared', detail: 'a ratio was zero or not finite' });
492
+ results.push({ id: entry.id, name: entry.name, kind: 'not-compared', detail: 'a ratio was zero or not finite', ...paired, ...targetVia });
172
493
  continue;
173
494
  }
174
- results.push(classify(entry, ratios, entry.epistemicStatus === 'fully-quantitative' || tabled !== undefined));
495
+ // A monomial-only record carries no prefactor. A fully-quantitative scalar AST does.
496
+ const recordsPrefactor = tabled !== undefined ||
497
+ boundGroup !== undefined ||
498
+ (entry.epistemicStatus === 'fully-quantitative' && entry.scalarAst !== undefined);
499
+ const extension = boundGroup !== undefined && groupSpec !== undefined
500
+ ? `the dimensionless group ${groupSpec.group} is bound, so the prefactor includes ${groupSpec.coefficient}·${groupSpec.group}^${groupSpec.exponent}`
501
+ : undefined;
502
+ const classified = classify(entry, ratios, recordsPrefactor);
503
+ results.push({
504
+ ...classified,
505
+ ...(extension !== undefined && classified.detail === undefined ? { detail: extension } : {}),
506
+ ...(names.length === 0 ? { constantsOnly: true } : {}),
507
+ ...paired, ...targetVia,
508
+ });
175
509
  }
176
- return results;
510
+ const label = overrideLabel(constantOverrides);
511
+ return label === undefined ? results : results.map((r) => ({ ...r, evaluatedAt: label }));
177
512
  }
178
513
  /**
179
514
  * Compare a `TARGET = EXPR` user equation (the `upt map --equation` input) with
180
515
  * the canonical registry. Names resolve onto `catalogDims` the way
181
516
  * `analyzeUserEquation` resolves them; `pi` and `tau` are the only named numbers.
517
+ * The right-hand side is dimension-checked through `parsePhysics` and evaluated by
518
+ * the active formula parser, the one `upt eval` uses, so a comparison accepts every
519
+ * function `eval` accepts (`ln(2)`, `asin`, `atan2`; persona finding W7). A registered
520
+ * constant takes its SI value, as in the canonical AST, unless
521
+ * `constantOverrides` replaces c, ħ, h or G (`--natural` / `--geometrized`).
182
522
  * Returns `[]` when the equation does not parse or no entry matches.
183
523
  *
184
524
  * @internal
185
525
  */
186
- export async function compareUserEquation(equation, catalogDims) {
187
- const eq = await parseUserEquation(equation);
188
- const catalogNames = new Set(catalogDims.keys());
189
- const resolved = new Map(eq.sources.map((s) => [s, resolveToCatalogName(s, catalogNames) ?? s]));
190
- const target = resolveToCatalogName(eq.target, catalogNames) ?? eq.target;
526
+ export async function compareUserEquation(equation, catalogDims, options) {
527
+ const dimsIn = new Map(catalogDims);
528
+ for (const [name, dim] of formulaNameDimensions()) {
529
+ if (!dimsIn.has(name))
530
+ dimsIn.set(name, dim);
531
+ }
532
+ const catalogNames = new Set(dimsIn.keys());
533
+ const bindShort = options?.bindShortNames === true;
534
+ const declined = (token) => !bindShort && token.length === 1 && catalogNames.has(token);
535
+ // W2: same kebab→underscore rewrite as analyzeUserEquation, so comparison and
536
+ // dimensional check see one formula.
537
+ const eq = await parseUserEquation(equation, catalogNames);
538
+ const resolved = new Map(eq.sources.map((s) => [s, declined(s) ? s : (resolveToCatalogName(s, catalogNames) ?? s)]));
539
+ const target = declined(eq.target) ? eq.target : (resolveToCatalogName(eq.target, catalogNames) ?? eq.target);
191
540
  const dims = {};
192
541
  for (const [name, c] of Object.entries(CONSTANTS))
193
542
  dims[name] = c.dim;
194
- for (const [s, r] of resolved)
195
- dims[s] = catalogDims.get(r) ?? DIMENSIONLESS;
196
- let expr;
543
+ for (const [s, r] of resolved) {
544
+ dims[s] = declined(s) ? DIMENSIONLESS : (dimsIn.get(r) ?? formulaSymbolDimension(s) ?? DIMENSIONLESS);
545
+ }
546
+ const rhs = eq.text.slice(eq.text.indexOf('=') + 1);
547
+ let compiled;
197
548
  try {
198
- expr = (await parsePhysics(equation.slice(equation.indexOf('=') + 1), dims)).expr;
549
+ await parsePhysics(rhs, dims);
550
+ compiled = (await getFormulaParser()).parse(rhs);
199
551
  }
200
552
  catch {
201
553
  return [];
202
554
  }
203
- return compareWithCanonical(target, [...resolved.values()], (values) => evalExpr(expr, {
204
- pi: Math.PI,
205
- tau: 2 * Math.PI,
555
+ const overrides = options?.constantOverrides;
556
+ const constantValues = Object.fromEntries(Object.entries(CONSTANTS).map(([name, c]) => [name, overrideValue(name, c.value, overrides)]));
557
+ // A name the catalog does not know carries no dimension, so it never pairs by dimension.
558
+ const sources = [...resolved.entries()].map(([token, r]) => {
559
+ if (declined(token))
560
+ return r;
561
+ const dim = dimsIn.get(r);
562
+ return dim === undefined ? r : { name: r, dim };
563
+ });
564
+ return compareWithCanonical(target, sources, (values) => compiled.evaluate({
565
+ ...constantValues,
206
566
  ...Object.fromEntries([...resolved].map(([s, r]) => [s, values[normalize(r)]])),
207
- }));
567
+ }), CANONICAL_EQUATIONS, overrides);
208
568
  }
209
569
  /**
210
570
  * The report lines for a comparison result, shared by `upt map --equation` and
@@ -219,15 +579,23 @@ export function describeComparisons(cs) {
219
579
  }
220
580
  /** One report line per comparison. @internal */
221
581
  export function describeComparison(c) {
222
- const who = `${c.id} (${c.name})`;
223
- const n = FIXED_POINT_EXPONENTS.length;
582
+ const pairs = [
583
+ ...(c.targetVia === undefined
584
+ ? []
585
+ : [`your target as its ${c.targetVia.its}, the target of ${c.targetVia.bridge}, which it restates`]),
586
+ ...(c.paired === undefined ? [] : [`${c.paired.map(([yours, its]) => `your ${yours} as its ${its}`).join(', ')}, paired by dimension`]),
587
+ ];
588
+ const who = `${c.id} (${c.name}${pairs.length === 0 ? '' : `; ${pairs.join('; ')}`})`;
589
+ const at = c.constantsOnly === true
590
+ ? `at the ${c.evaluatedAt ?? 'SI'} constant values (no free variable, so only the value is compared, not the form)`
591
+ : `at ${FIXED_POINT_EXPONENTS.length} fixed points${c.evaluatedAt === undefined ? '' : ` (${c.evaluatedAt})`}`;
224
592
  switch (c.kind) {
225
593
  case 'agrees':
226
- return `✓ agrees with ${who}, prefactor included: yours/canonical = 1 at ${n} fixed points`;
594
+ return `✓ agrees with ${who}, prefactor included: yours/canonical = 1 ${at}${c.detail ? ` (${c.detail})` : ''}`;
227
595
  case 'factor':
228
- return `⚠ differs from ${who} by a constant factor: yours/canonical = ${c.ratio.toPrecision(6)} at ${n} fixed points`;
596
+ return `⚠ differs from ${who} by a constant factor: yours/canonical = ${c.ratio.toPrecision(6)} ${at}`;
229
597
  case 'form':
230
- return `⚠ differs in FORM from ${who}: yours/canonical is not constant across ${n} fixed points`;
598
+ return `⚠ differs in FORM from ${who}: yours/canonical is not constant across ${FIXED_POINT_EXPONENTS.length} fixed points`;
231
599
  case 'prefactor-unchecked':
232
600
  return `· same form as ${who}, but ${c.detail}, so your prefactor is NOT checked`;
233
601
  case 'not-compared':