phylohist 0.1.0__tar.gz

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 (262) hide show
  1. phylohist-0.1.0/LICENSE +21 -0
  2. phylohist-0.1.0/PKG-INFO +319 -0
  3. phylohist-0.1.0/README.md +297 -0
  4. phylohist-0.1.0/phylohist/__init__.py +31 -0
  5. phylohist-0.1.0/phylohist/acts.py +35 -0
  6. phylohist-0.1.0/phylohist/blocks.py +342 -0
  7. phylohist-0.1.0/phylohist/claims.py +1340 -0
  8. phylohist-0.1.0/phylohist/cli.py +295 -0
  9. phylohist-0.1.0/phylohist/closure.py +413 -0
  10. phylohist-0.1.0/phylohist/derivatives.py +103 -0
  11. phylohist-0.1.0/phylohist/evaluation.py +279 -0
  12. phylohist-0.1.0/phylohist/loader/__init__.py +15 -0
  13. phylohist-0.1.0/phylohist/loader/checks.py +101 -0
  14. phylohist-0.1.0/phylohist/loader/corpus.py +78 -0
  15. phylohist-0.1.0/phylohist/loader/io.py +282 -0
  16. phylohist-0.1.0/phylohist/loader/load.py +582 -0
  17. phylohist-0.1.0/phylohist/loader/material.py +706 -0
  18. phylohist-0.1.0/phylohist/loader/nomenclature.py +293 -0
  19. phylohist-0.1.0/phylohist/loader/research.py +317 -0
  20. phylohist-0.1.0/phylohist/loader/taxa.py +1111 -0
  21. phylohist-0.1.0/phylohist/mcp.py +219 -0
  22. phylohist-0.1.0/phylohist/names.py +45 -0
  23. phylohist-0.1.0/phylohist/plan.py +269 -0
  24. phylohist-0.1.0/phylohist/ranks.py +112 -0
  25. phylohist-0.1.0/phylohist/regenerate.py +68 -0
  26. phylohist-0.1.0/phylohist/render.py +534 -0
  27. phylohist-0.1.0/phylohist/resolve.py +319 -0
  28. phylohist-0.1.0/phylohist/store.py +1733 -0
  29. phylohist-0.1.0/phylohist/table/1740_tilas.jsonl +3 -0
  30. phylohist-0.1.0/phylohist/table/1741_linnaeus.jsonl +4 -0
  31. phylohist-0.1.0/phylohist/table/1758_linnaeus.jsonl +751 -0
  32. phylohist-0.1.0/phylohist/table/1761_bohadsch.jsonl +33 -0
  33. phylohist-0.1.0/phylohist/table/1761_linnaeus.jsonl +118 -0
  34. phylohist-0.1.0/phylohist/table/1762_gaertner.jsonl +34 -0
  35. phylohist-0.1.0/phylohist/table/1766_linnaeus.jsonl +9 -0
  36. phylohist-0.1.0/phylohist/table/1766b_pallas.jsonl +334 -0
  37. phylohist-0.1.0/phylohist/table/1767_gunnerus.jsonl +17 -0
  38. phylohist-0.1.0/phylohist/table/1767_linnaeus.jsonl +333 -0
  39. phylohist-0.1.0/phylohist/table/1772_gyllenhaal.jsonl +12 -0
  40. phylohist-0.1.0/phylohist/table/1773_m/303/274ller.o.f.jsonl +44 -0
  41. phylohist-0.1.0/phylohist/table/1774_van phelsum.jsonl +4 -0
  42. phylohist-0.1.0/phylohist/table/1774a_m/303/274ller.o.f.jsonl +24 -0
  43. phylohist-0.1.0/phylohist/table/1774b_m/303/274ller.o.f.jsonl +36 -0
  44. phylohist-0.1.0/phylohist/table/1776_m/303/274ller.o.f.jsonl +348 -0
  45. phylohist-0.1.0/phylohist/table/1776_walch.jsonl +4 -0
  46. phylohist-0.1.0/phylohist/table/1778_klein.jsonl +2 -0
  47. phylohist-0.1.0/phylohist/table/1778_leske.jsonl +466 -0
  48. phylohist-0.1.0/phylohist/table/1789a_brugui/303/250re.jsonl +252 -0
  49. phylohist-0.1.0/phylohist/table/1791_brugui/303/250re.jsonl +17 -0
  50. phylohist-0.1.0/phylohist/table/1798_cuvier.jsonl +198 -0
  51. phylohist-0.1.0/phylohist/table/1801_lamarck.jsonl +275 -0
  52. phylohist-0.1.0/phylohist/table/1802_hisinger.jsonl +8 -0
  53. phylohist-0.1.0/phylohist/table/1815_lamarck.jsonl +9 -0
  54. phylohist-0.1.0/phylohist/table/1816a_lamarck.jsonl +312 -0
  55. phylohist-0.1.0/phylohist/table/1816b_lamarck.jsonl +840 -0
  56. phylohist-0.1.0/phylohist/table/1817a_cuvier.jsonl +7 -0
  57. phylohist-0.1.0/phylohist/table/1817b_cuvier.jsonl +35 -0
  58. phylohist-0.1.0/phylohist/table/1817c_cuvier.jsonl +0 -0
  59. phylohist-0.1.0/phylohist/table/1817d_cuvier.jsonl +73 -0
  60. phylohist-0.1.0/phylohist/table/1820_say.jsonl +5 -0
  61. phylohist-0.1.0/phylohist/table/1821_macleay.jsonl +83 -0
  62. phylohist-0.1.0/phylohist/table/1821_miller.j.s.jsonl +143 -0
  63. phylohist-0.1.0/phylohist/table/1821_wahlenberg.jsonl +35 -0
  64. phylohist-0.1.0/phylohist/table/1825a_say.jsonl +41 -0
  65. phylohist-0.1.0/phylohist/table/1825b_sowerby.g.b.jsonl +17 -0
  66. phylohist-0.1.0/phylohist/table/1825i_gray.j.e.jsonl +91 -0
  67. phylohist-0.1.0/phylohist/table/1826_meyer.jsonl +5 -0
  68. phylohist-0.1.0/phylohist/table/1826_schlotheim.jsonl +50 -0
  69. phylohist-0.1.0/phylohist/table/1828_hisinger.jsonl +55 -0
  70. phylohist-0.1.0/phylohist/table/1830_pander.jsonl +59 -0
  71. phylohist-0.1.0/phylohist/table/1837_hisinger.jsonl +59 -0
  72. phylohist-0.1.0/phylohist/table/1839_murchison.jsonl +59 -0
  73. phylohist-0.1.0/phylohist/table/1840_eichwald.jsonl +125 -0
  74. phylohist-0.1.0/phylohist/table/1840a_buch.jsonl +48 -0
  75. phylohist-0.1.0/phylohist/table/1840b_buch.jsonl +29 -0
  76. phylohist-0.1.0/phylohist/table/1842_conrad.t.a.jsonl +19 -0
  77. phylohist-0.1.0/phylohist/table/1842_vanuxem.jsonl +28 -0
  78. phylohist-0.1.0/phylohist/table/1842_volborth.jsonl +18 -0
  79. phylohist-0.1.0/phylohist/table/1843_hall.jsonl +37 -0
  80. phylohist-0.1.0/phylohist/table/1844_buch.jsonl +57 -0
  81. phylohist-0.1.0/phylohist/table/1845_buch.jsonl +72 -0
  82. phylohist-0.1.0/phylohist/table/1846a_buch.jsonl +4 -0
  83. phylohist-0.1.0/phylohist/table/1847_hall.jsonl +92 -0
  84. phylohist-0.1.0/phylohist/table/1848_leuckart.jsonl +20 -0
  85. phylohist-0.1.0/phylohist/table/1848b_forbes.jsonl +129 -0
  86. phylohist-0.1.0/phylohist/table/1852_hall.jsonl +210 -0
  87. phylohist-0.1.0/phylohist/table/1854_m/303/274ller.j.p.jsonl +83 -0
  88. phylohist-0.1.0/phylohist/table/1854a_billings.jsonl +10 -0
  89. phylohist-0.1.0/phylohist/table/1854b_billings.jsonl +18 -0
  90. phylohist-0.1.0/phylohist/table/1854c_billings.jsonl +32 -0
  91. phylohist-0.1.0/phylohist/table/1857_billings.jsonl +181 -0
  92. phylohist-0.1.0/phylohist/table/1858_salter_billings.jsonl +13 -0
  93. phylohist-0.1.0/phylohist/table/1858a_billings.jsonl +119 -0
  94. phylohist-0.1.0/phylohist/table/1858b_billings.jsonl +41 -0
  95. phylohist-0.1.0/phylohist/table/1887_billings.w.r.jsonl +16 -0
  96. phylohist-0.1.0/phylohist/table/1896_pompeckj.jsonl +26 -0
  97. phylohist-0.1.0/phylohist/table/1897_whiteaves.jsonl +20 -0
  98. phylohist-0.1.0/phylohist/table/1898_whiteaves.jsonl +8 -0
  99. phylohist-0.1.0/phylohist/table/1900_bather.jsonl +134 -0
  100. phylohist-0.1.0/phylohist/table/1914c_bather.jsonl +18 -0
  101. phylohist-0.1.0/phylohist/table/1935_bassler.jsonl +395 -0
  102. phylohist-0.1.0/phylohist/table/1936_bassler.jsonl +218 -0
  103. phylohist-0.1.0/phylohist/table/1941_whitehouse.jsonl +60 -0
  104. phylohist-0.1.0/phylohist/table/1960_gill_caster.jsonl +112 -0
  105. phylohist-0.1.0/phylohist/table/1961_dehm.jsonl +40 -0
  106. phylohist-0.1.0/phylohist/table/1961_rievers.jsonl +7 -0
  107. phylohist-0.1.0/phylohist/table/1962_fay.jsonl +15 -0
  108. phylohist-0.1.0/phylohist/table/1963_brown.i.a.jsonl +18 -0
  109. phylohist-0.1.0/phylohist/table/1963_durham_caster.jsonl +17 -0
  110. phylohist-0.1.0/phylohist/table/1965_fell.jsonl +113 -0
  111. phylohist-0.1.0/phylohist/table/1966_durham.jsonl +14 -0
  112. phylohist-0.1.0/phylohist/table/1966_durham_caster.jsonl +19 -0
  113. phylohist-0.1.0/phylohist/table/1966_kesling.jsonl +53 -0
  114. phylohist-0.1.0/phylohist/table/1966_regn/303/251ll.jsonl +166 -0
  115. phylohist-0.1.0/phylohist/table/1967_paul.c.r.c.jsonl +56 -0
  116. phylohist-0.1.0/phylohist/table/1967a_durham.jsonl +16 -0
  117. phylohist-0.1.0/phylohist/table/1967a_fay.jsonl +19 -0
  118. phylohist-0.1.0/phylohist/table/1967a_ubaghs.jsonl +52 -0
  119. phylohist-0.1.0/phylohist/table/1967b_durham.jsonl +15 -0
  120. phylohist-0.1.0/phylohist/table/1967b_fay.jsonl +18 -0
  121. phylohist-0.1.0/phylohist/table/1967c_durham.jsonl +41 -0
  122. phylohist-0.1.0/phylohist/table/1967e_ubaghs.jsonl +20 -0
  123. phylohist-0.1.0/phylohist/table/1968_webby.jsonl +22 -0
  124. phylohist-0.1.0/phylohist/table/1968a_paul.c.r.c.jsonl +10 -0
  125. phylohist-0.1.0/phylohist/table/1968b_paul.c.r.c.jsonl +194 -0
  126. phylohist-0.1.0/phylohist/table/1969_robison_sprinkle.jsonl +15 -0
  127. phylohist-0.1.0/phylohist/table/1970_mintz.jsonl +16 -0
  128. phylohist-0.1.0/phylohist/table/1971_paul.c.r.c.jsonl +5 -0
  129. phylohist-0.1.0/phylohist/table/1972_paul.c.r.c.jsonl +3 -0
  130. phylohist-0.1.0/phylohist/table/1973_sprinkle.jsonl +1044 -0
  131. phylohist-0.1.0/phylohist/table/1975_bell.b.m.jsonl +45 -0
  132. phylohist-0.1.0/phylohist/table/1975_broadhead_strimple.jsonl +13 -0
  133. phylohist-0.1.0/phylohist/table/1975_kolata.jsonl +385 -0
  134. phylohist-0.1.0/phylohist/table/1976_bell.b.m.jsonl +272 -0
  135. phylohist-0.1.0/phylohist/table/1976_bell.b.m_petersen.m.s.jsonl +15 -0
  136. phylohist-0.1.0/phylohist/table/1978_bell.b.m_sprinkle.jsonl +17 -0
  137. phylohist-0.1.0/phylohist/table/1978_durham.jsonl +9 -0
  138. phylohist-0.1.0/phylohist/table/1979_guensburg.jsonl +19 -0
  139. phylohist-0.1.0/phylohist/table/1980_bell.b.m.jsonl +107 -0
  140. phylohist-0.1.0/phylohist/table/1980_sprinkle.jsonl +73 -0
  141. phylohist-0.1.0/phylohist/table/1981_bockelie.jsonl +70 -0
  142. phylohist-0.1.0/phylohist/table/1981_derstler.jsonl +23 -0
  143. phylohist-0.1.0/phylohist/table/1982_bell.b.m.jsonl +39 -0
  144. phylohist-0.1.0/phylohist/table/1982_broadhead.jsonl +61 -0
  145. phylohist-0.1.0/phylohist/table/1982_kolata.jsonl +14 -0
  146. phylohist-0.1.0/phylohist/table/1982_smith.a.b.jsonl +13 -0
  147. phylohist-0.1.0/phylohist/table/1982_sprinkle_parsley.jsonl +17 -0
  148. phylohist-0.1.0/phylohist/table/1982a_parsley.jsonl +74 -0
  149. phylohist-0.1.0/phylohist/table/1982b_parsley.jsonl +28 -0
  150. phylohist-0.1.0/phylohist/table/1982c_parsley.jsonl +25 -0
  151. phylohist-0.1.0/phylohist/table/1982g_sprinkle.jsonl +75 -0
  152. phylohist-0.1.0/phylohist/table/1982h_sprinkle.jsonl +18 -0
  153. phylohist-0.1.0/phylohist/table/1982i_sprinkle.jsonl +20 -0
  154. phylohist-0.1.0/phylohist/table/1983_bockelie_paul.c.r.c.jsonl +32 -0
  155. phylohist-0.1.0/phylohist/table/1983_brett_frest_sprinkle_clement.c.r.jsonl +23 -0
  156. phylohist-0.1.0/phylohist/table/1983_holloway_jell.jsonl +62 -0
  157. phylohist-0.1.0/phylohist/table/1983_jell.jsonl +54 -0
  158. phylohist-0.1.0/phylohist/table/1985_fatka_kordule.jsonl +12 -0
  159. phylohist-0.1.0/phylohist/table/1985_jell_burrett_banks.jsonl +84 -0
  160. phylohist-0.1.0/phylohist/table/1985_smith.a.b.jsonl +175 -0
  161. phylohist-0.1.0/phylohist/table/1985_sprinkle.jsonl +16 -0
  162. phylohist-0.1.0/phylohist/table/1987_gehling.jsonl +16 -0
  163. phylohist-0.1.0/phylohist/table/1987_lewis.r.d_sprinkle_bailey.j.b_moffit.j_parsley.jsonl +16 -0
  164. phylohist-0.1.0/phylohist/table/1987_smith.a.b_arbizu.jsonl +63 -0
  165. phylohist-0.1.0/phylohist/table/1987_ubaghs.jsonl +28 -0
  166. phylohist-0.1.0/phylohist/table/1988_guensburg.jsonl +46 -0
  167. phylohist-0.1.0/phylohist/table/1988_ubaghs_robison.jsonl +42 -0
  168. phylohist-0.1.0/phylohist/table/1990_fatka_kordule.jsonl +12 -0
  169. phylohist-0.1.0/phylohist/table/1990_smith.a.b_jell.jsonl +158 -0
  170. phylohist-0.1.0/phylohist/table/1990_ubaghs_vizca/303/257no.jsonl +12 -0
  171. phylohist-0.1.0/phylohist/table/1991_fatka_kordule.jsonl +14 -0
  172. phylohist-0.1.0/phylohist/table/1992_sumrall.jsonl +14 -0
  173. phylohist-0.1.0/phylohist/table/1993_dzik_or/305/202owski.jsonl +14 -0
  174. phylohist-0.1.0/phylohist/table/1993_sumrall.jsonl +41 -0
  175. phylohist-0.1.0/phylohist/table/1993_young.t.p_donovan.s.k.jsonl +19 -0
  176. phylohist-0.1.0/phylohist/table/1994_guensburg_sprinkle.jsonl +351 -0
  177. phylohist-0.1.0/phylohist/table/1994_sprinkle_wahlman.jsonl +55 -0
  178. phylohist-0.1.0/phylohist/table/1995_dzik_or/305/202owski.jsonl +10 -0
  179. phylohist-0.1.0/phylohist/table/1996_sumrall.jsonl +68 -0
  180. phylohist-0.1.0/phylohist/table/1996_sumrall_bowsher.jsonl +21 -0
  181. phylohist-0.1.0/phylohist/table/1997_paul.c.r.c.jsonl +175 -0
  182. phylohist-0.1.0/phylohist/table/1997_sumrall_sprinkle_guensburg.jsonl +99 -0
  183. phylohist-0.1.0/phylohist/table/1998_dean.j_smith.a.b.jsonl +33 -0
  184. phylohist-0.1.0/phylohist/table/1999_dom/303/255nguez alonso.jsonl" +80 -0
  185. phylohist-0.1.0/phylohist/table/1999_ubaghs.jsonl +52 -0
  186. phylohist-0.1.0/phylohist/table/1999_zhao.y.l_yuan.j.l_zhu.m.y_yang.r.d_guo.q.j_qian.y_huang.y.z_pan.y.jsonl +81 -0
  187. phylohist-0.1.0/phylohist/table/2000_grigo.jsonl +45 -0
  188. phylohist-0.1.0/phylohist/table/2000_sumrall_garbisch_pope.j.p.jsonl +63 -0
  189. phylohist-0.1.0/phylohist/table/2001_rozhnov_fedorov.jsonl +17 -0
  190. phylohist-0.1.0/phylohist/table/2001_sumrall.jsonl +22 -0
  191. phylohist-0.1.0/phylohist/table/2001_sumrall_sprinkle_guensburg.jsonl +12 -0
  192. phylohist-0.1.0/phylohist/table/2002_gil cid_dom/303/255nguez alonso.jsonl" +8 -0
  193. phylohist-0.1.0/phylohist/table/2003_guensburg_sprinkle.jsonl +122 -0
  194. phylohist-0.1.0/phylohist/table/2003_sumrall_parsley.jsonl +10 -0
  195. phylohist-0.1.0/phylohist/table/2004_parsley_prokop.jsonl +30 -0
  196. phylohist-0.1.0/phylohist/table/2005_frest.jsonl +21 -0
  197. phylohist-0.1.0/phylohist/table/2006_parsley_zhao.y.l.jsonl +58 -0
  198. phylohist-0.1.0/phylohist/table/2006_sprinkle_collins.d.jsonl +34 -0
  199. phylohist-0.1.0/phylohist/table/2006_sumrall_brett_cornell.jsonl +18 -0
  200. phylohist-0.1.0/phylohist/table/2006_sumrall_gahn.jsonl +75 -0
  201. phylohist-0.1.0/phylohist/table/2006_sumrall_sprinkle_bonem.jsonl +40 -0
  202. phylohist-0.1.0/phylohist/table/2007_hu.s.x_luo.h.l_hou.s.g_erdtmann.jsonl +4 -0
  203. phylohist-0.1.0/phylohist/table/2007_zhao.y.l_parsley_peng.j.jsonl +15 -0
  204. phylohist-0.1.0/phylohist/table/2007a_nardin.jsonl +17 -0
  205. phylohist-0.1.0/phylohist/table/2007b_nardin.jsonl +8 -0
  206. phylohist-0.1.0/phylohist/table/2008_luo.h.l_li.y_hu.s.x_fu.x.p_hou.s.g_liu.x.r_chen.l.z_li.j.f_pang.j.y_liu.q.jsonl +10 -0
  207. phylohist-0.1.0/phylohist/table/2008_zhao.y.l_parsley_peng.j.jsonl +19 -0
  208. phylohist-0.1.0/phylohist/table/2009_guensburg_sprinkle.jsonl +47 -0
  209. phylohist-0.1.0/phylohist/table/2009_sumrall.jsonl +12 -0
  210. phylohist-0.1.0/phylohist/table/2009_sumrall_brett_mckinney.jsonl +14 -0
  211. phylohist-0.1.0/phylohist/table/2009_zamora_gozalo_li/303/261/303/241n.jsonl +20 -0
  212. phylohist-0.1.0/phylohist/table/2010_liu.q_hu.s.x_zhang.z_cuevas-castell_gong.y.m_tao.j.l.jsonl +30 -0
  213. phylohist-0.1.0/phylohist/table/2010_m/303/274ller.p_hahn.jsonl +121 -0
  214. phylohist-0.1.0/phylohist/table/2010_parsley_zhao.y.l.jsonl +17 -0
  215. phylohist-0.1.0/phylohist/table/2010_sumrall.jsonl +28 -0
  216. phylohist-0.1.0/phylohist/table/2010_zamora_smith.a.b.jsonl +16 -0
  217. phylohist-0.1.0/phylohist/table/2010_zhao.y.l_sumrall_parsley_peng.j.jsonl +14 -0
  218. phylohist-0.1.0/phylohist/table/2011_sprinkle_parsley_zhao.y.l_peng.j.jsonl +20 -0
  219. phylohist-0.1.0/phylohist/table/2011_sumrall_zamora.jsonl +115 -0
  220. phylohist-0.1.0/phylohist/table/2012_doweld.jsonl +66 -0
  221. phylohist-0.1.0/phylohist/table/2012_zamora_smith.a.b.jsonl +48 -0
  222. phylohist-0.1.0/phylohist/table/2013_m/303/274ller.p_hahn_bohat/303/275.jsonl +32 -0
  223. phylohist-0.1.0/phylohist/table/2013_nardin_bohat/303/275.jsonl +72 -0
  224. phylohist-0.1.0/phylohist/table/2013_smith.a.b_zamora.jsonl +31 -0
  225. phylohist-0.1.0/phylohist/table/2013_sumrall_heredia_rodr/303/255guez.c.m_mestre.jsonl +62 -0
  226. phylohist-0.1.0/phylohist/table/2013_zamora.jsonl +36 -0
  227. phylohist-0.1.0/phylohist/table/2013_zamora_sumrall_vizca/303/257no.jsonl +16 -0
  228. phylohist-0.1.0/phylohist/table/2014_chen.g.y_han.n.r.jsonl +10 -0
  229. phylohist-0.1.0/phylohist/table/2014_jell.jsonl +22 -0
  230. phylohist-0.1.0/phylohist/table/2014_makhlouf_lefebvre_nardin_nedjari_r/303/251gnault_ferhi.jsonl +19 -0
  231. phylohist-0.1.0/phylohist/table/2014_zhu.x.j_zamora_lefebvre.jsonl +13 -0
  232. phylohist-0.1.0/phylohist/table/2015_rahman_stewart_zamora.jsonl +13 -0
  233. phylohist-0.1.0/phylohist/table/2015_sprinkle_sumrall.jsonl +25 -0
  234. phylohist-0.1.0/phylohist/table/2015_sumrall_zamora.jsonl +13 -0
  235. phylohist-0.1.0/phylohist/table/2015_yang.z.c_lin.j.p_zhang.y.p_wu.y.s_meng.x.y.jsonl +18 -0
  236. phylohist-0.1.0/phylohist/table/2015_zamora_sumrall_sprinkle.jsonl +15 -0
  237. phylohist-0.1.0/phylohist/table/2015_zhao.y.l_peng.j_wu.m.y_luo.x.c_wen.r.q_liu.y.j.jsonl +16 -0
  238. phylohist-0.1.0/phylohist/table/2017_allaire_lefebvre_nardin_martin.e.l.o_vaucher_escarguel.jsonl +41 -0
  239. phylohist-0.1.0/phylohist/table/2017_briggs.d.e.g_siveter.de.j_siveter.da.j_sutton.m.d_rahman.jsonl +16 -0
  240. phylohist-0.1.0/phylohist/table/2017_nardin_lefebvre_fatka_nohejlov/303/241_ka/305/241i/304/215a_/305/241in/303/241gl_szabad.jsonl +70 -0
  241. phylohist-0.1.0/phylohist/table/2017_zamora_sumrall_zhu.x.j_lefebvre.jsonl +64 -0
  242. phylohist-0.1.0/phylohist/table/2018_lefebvre_lerosey-aubril.jsonl +17 -0
  243. phylohist-0.1.0/phylohist/table/2019_nohejlov/303/241_nardin_fatka_ka/305/241i/304/215a_szabad.jsonl +30 -0
  244. phylohist-0.1.0/phylohist/table/2019_wen.r.q_babcock_peng.j_robison.jsonl +13 -0
  245. phylohist-0.1.0/phylohist/table/2020_ewin_martin.m_isotalo_zamora.jsonl +93 -0
  246. phylohist-0.1.0/phylohist/table/2020_guensburg_sprinkle_mooi_lefebvre_david_roux_derstler.jsonl +161 -0
  247. phylohist-0.1.0/phylohist/table/2020_zamora_sprinkle_sumrall.jsonl +26 -0
  248. phylohist-0.1.0/phylohist/table/2021_jell_sprinkle.jsonl +94 -0
  249. phylohist-0.1.0/phylohist/table/2021_parsley.jsonl +32 -0
  250. phylohist-0.1.0/phylohist/table/2022_deshmukh.jsonl +10 -0
  251. phylohist-0.1.0/phylohist/table/2022_zamora_rahman_sumrall_gibson_thompson.jsonl +86 -0
  252. phylohist-0.1.0/phylohist/table/2022_zhao.j_guo.j_selden_cong.p.y_li.y.j.jsonl +17 -0
  253. phylohist-0.1.0/phylohist/table/2022_zhao.j_rahman_zamora_chen.a_cong.p.y.jsonl +26 -0
  254. phylohist-0.1.0/phylohist/table/2024_wang.d.z_nohejlov/303/241_sun.z.x_zeng.h_lefebvre_yang.x.l_zhao.f.c.jsonl +14 -0
  255. phylohist-0.1.0/phylohist/table/2024_zamora_guensburg_sprinkle.jsonl +23 -0
  256. phylohist-0.1.0/phylohist/table/manifest.json +30046 -0
  257. phylohist-0.1.0/phylohist/table/names.json +46279 -0
  258. phylohist-0.1.0/phylohist/table/ranks.yaml +112 -0
  259. phylohist-0.1.0/phylohist/table/repositories.json +496 -0
  260. phylohist-0.1.0/phylohist/tools.py +529 -0
  261. phylohist-0.1.0/phylohist/words.py +935 -0
  262. phylohist-0.1.0/pyproject.toml +77 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Henry H. Andrews
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,319 @@
1
+ Metadata-Version: 2.4
2
+ Name: phylohist
3
+ Version: 0.1.0
4
+ Summary: Published taxonomic opinions on Palaeozoic echinoderms, recorded as printed, with tools that answer from them
5
+ License-Expression: MIT
6
+ License-File: LICENSE
7
+ Keywords: taxonomy,phylogenetics,palaeontology,echinoderms,nomenclature,mcp,human-in-the-loop,local-first
8
+ Author: Henry H. Andrews
9
+ Author-email: henry@henryandrews.net
10
+ Requires-Python: >=3.12,<4
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
15
+ Requires-Dist: coloredlog (>=0.2.5,<0.3)
16
+ Requires-Dist: json-schema-engine (>=0.0.6,<0.0.7)
17
+ Requires-Dist: mcp (>=2.2.0,<3)
18
+ Requires-Dist: pyyaml (>=6.0.3,<7)
19
+ Project-URL: Repository, https://github.com/handrews/phylohist
20
+ Description-Content-Type: text/markdown
21
+
22
+ # Phylohist: Exploring changes in systematics over time
23
+
24
+ Science is always in motion. Most online taxonomy or phylogeny
25
+ databases attempt to show a consensus or accepted view, with
26
+ each site having its own editorial policy for what gets included.
27
+ Some include historical information, but do not make it a central
28
+ or easily-accessible part of the sysetm.
29
+
30
+ The `phylohist` project instead provides access to trees as published,
31
+ over time, while leaving the judgement of what to accept or reject to
32
+ the researcher. An LLM-driven interface supports complex queries over
33
+ a curated corpus stored as YAML data. This uses a model where one is
34
+ needed, and prioritizes reliability, reproducibility, speed,
35
+ and lower costs where one is not.
36
+
37
+ The current corpus holds over 200 papers entered in whole or in part, from
38
+ the mid-1700s to the present, mostly focusing on Paleozoic echinoderms.
39
+ A coverage system tracks how much of the information from a paper has
40
+ been entered and reviewed.
41
+
42
+ ## Status and future plans
43
+
44
+ This repository began as a place to store my notes, and gradually evolved
45
+ into a software package, featuring more and more modern software engineering
46
+ best practices as I have found time to add them. However, it remains
47
+ a solo, unfunded project that I work on whenever I can.
48
+
49
+ The package is published on PyPI as `phylohist` from version 0.1.0.
50
+ Next steps include writing human-user-friendly documentation,
51
+ continuing to improve the software development methodology, curating
52
+ additional data and adding more features.
53
+
54
+ A data model for capturing specimen information has recenlty been
55
+ designed but data entry for this area is in its infancy. Additional
56
+ areas of fuure work are proper support for cladograms (currently
57
+ allowed in the data but treated more-or-less like systematic trees)
58
+ and data visualization.
59
+
60
+ ## Corpus Scope and Editorial Curation Policy
61
+
62
+ Because `phylohist` relies on manual validation and a human-in-the-loop
63
+ workflow, data ingestion proceeds slowly to prioritize high fidelity
64
+ over unchecked volume.
65
+
66
+ No data is entered purely by AI. The data model has grown from my experience
67
+ of manually reading papers and figuring out how to work with the data as
68
+ it was published. Current LLMs are too eager to make things "work" rather
69
+ than step back and consider the user experience.
70
+
71
+ ### Intentional Scoping and Partial Entry
72
+
73
+ Data entry is guided by the target research scope, currently focusing primarily
74
+ on Paleozoic echinoderms and their relatives in the Ambulacrarian stem group.
75
+
76
+ * **Partial Ingestion:** For vast foundational texts such as Linnaeus’s
77
+ *Systema Naturae*, only the specific branches of interest to the active
78
+ dataset are entered.
79
+ * **Closed-World Boundaries:** The data model is being enhanced with ways
80
+ to indicate when data is complete by some metric. However, updating
81
+ the data with these fields is itself a large, ongoing project.
82
+
83
+ ### Archival Fidelity vs. Modern Interpretation
84
+
85
+ Tracking archaic, text-heavy literature (particularly pre-19th-century sources
86
+ written in informal prose) presents a unique archival challenge.
87
+
88
+ * **Philosophy:** The core directive of this corpus is to capture the published
89
+ author's opinions *as they published them*. However, no data model is
90
+ perfect, so `phylohist` attempts to get as close as possible while
91
+ capturing literal text and editorial reasoning to inform users of
92
+ possible discrepancies and inferences. Only ICZN-mandated
93
+ textual normalizations are performed. In more recently-entered data,
94
+ the original textual form is also captured (e.g. "Asterias caputmedusae"
95
+ vs "Aſterias Caput meduſæ"). The common use of only non-Latin names for
96
+ higher taxa in earlier publications introduces further difficulty, as
97
+ does the uneven introduction of ranks other than those first used by Linnaeus.
98
+ * **Continuous Ingestion:** Determining how to translate loose, informal
99
+ prose into deterministic YAML schemas without breaking historical context
100
+ is an ongoing design effort. Often, a paper will inspire a revision
101
+ to the data model, meaning that data entered at different times shows
102
+ different levels of completion. Older data may use less precise structures
103
+ that will eventually brought in line with the current design so that
104
+ the older structures can be dropped.
105
+
106
+ *The project welcomes feedback or additions to schemas and coverage maps
107
+ via GitHub issues. Please open an issue prior to working on a pull request
108
+ to ensure that the request will be well-received.*
109
+
110
+ ## Humans, Models, and Code
111
+
112
+ The internet has made a tremendous amount of information available,
113
+ but finding what you need and verifying its accuracy is a lot of work.
114
+ Humans have the deepest judgement for data curation, while models
115
+ handle flexible querying beyond what fixed database queries can provide.
116
+ Underneath it all, deterministic code ensures fast, repeatable, and
117
+ accurate outcomes.
118
+
119
+ This diagram shows the roles of humans (the top row), models (the middle)
120
+ and code. The third column shows the expected typical interactive usage,
121
+ where the model interprets the questions and chooses the tools to call and
122
+ output shapes to render, but leaves the querying and output construction
123
+ to code.
124
+
125
+ This avoids verbose or hallucinated output while spending tokens only
126
+ on the work that really requires a model's reasoning and flexibility.
127
+
128
+ <picture>
129
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/handrews/phylohist/main/docs/architecture-dark.svg">
130
+ <img alt="How phylohist fits together: three lanes, human, model and code, read in four columns, the data, the CLI, chat and the eval" src="https://raw.githubusercontent.com/handrews/phylohist/main/docs/architecture.svg">
131
+ </picture>
132
+
133
+ - **The data.** The curator records each publication's opinions as
134
+ printed: who published what systematic information in which paper.
135
+ That is names and nomenclatural acts, placements, usages and
136
+ synonymies, the specimens they rest on with their geological context,
137
+ and the page, plate and figure numbers that locate each of these. It
138
+ is not diagnoses, descriptions or a narration of the paper; a
139
+ researcher who wants those follows the citation to the paper itself.
140
+ The model's part is optional and reviewable: it reads a
141
+ paper against its tree and writes a review (`notes/reviews/`), or
142
+ drafts a tree (`drafts/`) that code validates and the researcher
143
+ audits before it enters `data/`. The human and the model review each
144
+ other's work; code checks both against the schema and regenerates the
145
+ claim table, which CI keeps current.
146
+ - **The CLI.** A question goes from the researcher to the tools with no
147
+ model in the lane: `phylohist history rhenopyrgus` renders the block.
148
+ - **Chat.** Claude asks the MCP server. The model resolves the
149
+ names and papers the question mentions and states a plan, the blocks
150
+ the answer is made of; code builds and renders them. The model
151
+ chooses; code answers. The only words of the model's own that reach a
152
+ reader are a one-line header stating the parameters it chose.
153
+ - **The eval.** The runner drives the model over the committed
154
+ questions in compose or planner mode, the grader is code, and a model
155
+ judges only the header. The researcher writes the questions and
156
+ reviews the grades and write-ups (`eval/`).
157
+
158
+ ## Correctness, Performance, and Cost
159
+
160
+ The project's evolution can be seen through the evaluation
161
+ [metrics](https://github.com/handrews/phylohist/blob/main/eval/findings/metrics.md).
162
+
163
+ Moving from AI-written prose answers to planned queries with modular
164
+ output blocks improved key measurements across complete evaluation runs:
165
+
166
+ * The measured pass rate rose from 61% to 87% on the original question
167
+ set, with several failure modes eliminated entirely; the latest run
168
+ (2026-11-02, the run version 0.1.0 ships with) passes 80% of those
169
+ questions and 80% of the expanded set of 56.
170
+ * Wall clock time was cut from around 25 minutes to around 10 minutes,
171
+ over a quarter more questions.
172
+ * Token usage dropped from 2.25 million to 0.60 million.
173
+
174
+ Future improvements to how the model selects blocks are expected to raise
175
+ the correctness score.
176
+
177
+ ## Tools and MCP
178
+
179
+ The `phylohist` CLI runs queries over the claims table generated from
180
+ the curated YAML data. These result in output data blocks rendered
181
+ as text, Markdown, or JSON based on the `--style` argument.
182
+
183
+ The CLI has one subcommand per tool:
184
+
185
+ poetry run phylohist resolve "Palæaster"
186
+ poetry run phylohist contents 1994_guensburg_sprinkle astrocystitidae --synonymy
187
+ poetry run phylohist descendants edrioblastoidea
188
+ poetry run phylohist ancestors astrocystitidae cyathocystidae rhenopyrgidae
189
+ poetry run phylohist history rhenopyrgus --style markdown
190
+ poetry run phylohist history "Rhenopyrgus grayae"
191
+ poetry run phylohist under rhenopyrgus edrioblastoidina
192
+ poetry run phylohist statements "Rhenopyrgus viviani"
193
+ poetry run phylohist gap "Holloway & Jell 1983" material
194
+ poetry run phylohist source "Lamarck 1816"
195
+ poetry run phylohist plan my-plan.yaml
196
+ poetry run python scripts/eval_run.py --mode planner --ask "Who first placed Rhenopyrgus under Edrioblastoidina?"
197
+
198
+ The same tools are served over MCP by the `phylohist-mcp` command
199
+ (`phylohist/mcp.py`), which `.mcp.json` registers for Claude Code:
200
+ a chat model can read blocks or state a plan and get the rendered answer.
201
+ The "Reading the table" section of `docs/claims.md` describes the blocks
202
+ and the tools.
203
+
204
+ ### Tool Examples
205
+
206
+ What one paper places in a family, showing only what the paper included:
207
+
208
+ $ poetry run phylohist contents 1994_guensburg_sprinkle astrocystitidae
209
+ Guensburg & Sprinkle 1994
210
+ Family Astrocystitidae emend.
211
+ Genus Astrocystites
212
+ Genus Cambroblastus
213
+ Genus Lampteroblastus gen. nov.
214
+ Type species. Lampteroblastus hintzei
215
+ Lampteroblastus hintzei sp. nov.
216
+
217
+ The emendation, the new genus and species, and the type species are the
218
+ paper's own statements; nothing here is inferred, and a source whose
219
+ listing is not yet entered says so instead.
220
+
221
+ See [`docs/walkthrough.md`](https://github.com/handrews/phylohist/blob/main/docs/walkthrough.md) for additional examples.
222
+
223
+ ### Asking from the CLI
224
+
225
+ The `eval_run.py` script can be used to ask a question without using the
226
+ chat interface to see how the model plans the queries and selects the output
227
+ blocks. It requires an Anthropic API key to be configured.
228
+
229
+ poetry run python scripts/eval_run.py --ask "Who first placed Rhenopyrgus under Edrioblastoidina?"
230
+
231
+ Rhenopyrgus (including its subgenus rank variant) placed under Edrioblastoidina (= Edrioblastoidea); taxonomy tree, all years
232
+
233
+ Rhenopyrgus Dehm 1961 under Edrioblastoidina Fay 1962: 4 papers, 4 co-author sets, 1994–2020
234
+ first Guensburg & Sprinkle 1994, last Ewin et al. 2020
235
+
236
+ 1994 Guensburg & Sprinkle Cyathocystidae › Rhenopyrginae › Rhenopyrgus
237
+ 2000 Grigo Cyathocystidae › Rhenopyrginae › Rhenopyrgus
238
+ 2013 Sumrall et al. Rhenopyrgidae › Rhenopyrgus
239
+ 2020 Ewin et al. Rhenopyrgidae › Rhenopyrgus
240
+
241
+ --- trail
242
+ resolve_name {"query": "Rhenopyrgus"} -> 2 candidate(s)
243
+ resolve_name {"query": "Edrioblastoidina"} -> 1 candidate(s)
244
+ placed_under {"record": "rhenopyrgus", "parent": "edrioblastoidina", "include_variants": true} -> 1 block(s)
245
+ header: Rhenopyrgus (including its subgenus rank variant) placed under Edrioblastoidina (= Edrioblastoidea); taxonomy tree, all years
246
+ 21227+375 tokens, 6.9s, tool_use
247
+
248
+ ## Install
249
+
250
+ From PyPI, for the tools and the MCP server over the claim table as of
251
+ the release (Python 3.12 or later):
252
+
253
+ pip install phylohist
254
+ phylohist history rhenopyrgus
255
+ phylohist-mcp
256
+
257
+ The second command is the server over stdio, which any MCP client runs
258
+ by name. For Claude Desktop or Claude Code the entry is
259
+
260
+ {"mcpServers": {"phylohist": {"command": "phylohist-mcp"}}}
261
+
262
+ or, with nothing installed, `uvx --from phylohist phylohist-mcp` as the
263
+ command and its arguments.
264
+
265
+ From a checkout, for the loader, the generator and the eval,
266
+ [Poetry](https://python-poetry.org/):
267
+
268
+ poetry install
269
+
270
+ The claim table the tools read is generated into `phylohist/table/`, so
271
+ a built package carries the table as of its build and a clone answers
272
+ from the table as `poetry run regenerate` last wrote it.
273
+ `PHYLOHIST_CLAIMS` names another table to read.
274
+
275
+ Only `scripts/eval_run.py` and the grader's `--judge` call a model;
276
+ their client is the `eval` dependency group, and they read
277
+ `ANTHROPIC_API_KEY` from the environment or from a git-ignored `.env` at
278
+ the repository root. Nothing else needs a key.
279
+
280
+ ## Checks
281
+
282
+ CI runs these on Python 3.12 and 3.14 and fails if the generated
283
+ schema census, the claim table or the expected-warnings file is stale;
284
+ after editing `data/` or the schema, `poetry run regenerate` rewrites all
285
+ three (a warning the load no longer produces leaves the file; a new one
286
+ is added with `scripts/expected_warnings.py --add`):
287
+
288
+ poetry run ruff check .
289
+ poetry run ruff format --check .
290
+ poetry run pytest --cov=phylohist --cov-fail-under=90
291
+ poetry run regenerate
292
+ git diff --exit-code scripts/schema-usage.md phylohist/table/ tests/expected-warnings.txt
293
+ poetry run python scripts/check_draft.py drafts/<file>.yaml
294
+
295
+ The tests run over the frozen copy of the data under `tests/corpus/`;
296
+ only those marked `production` load `data/` itself, so improving the
297
+ data cannot break a test of the code. `poetry run pytest --demo` adds the
298
+ eval questions and the walkthrough over the committed `phylohist/table/`, which
299
+ hold for the data they were last refreshed against.
300
+
301
+ ## Where things are
302
+
303
+ * `docs/` will contain user documentation; for now it explains how
304
+ recorded tree data is converted to the claims that the tools use,
305
+ as well as the tools and the answer formats.
306
+ * `notes/` contains project development information from both the human
307
+ and LLM developers; some of this information might be out-of-date.
308
+ * `eval/` holds the evaluation questions, results, write-ups, and metrics.
309
+ * `drafts/` holds AI-drafted trees awaiting a human audit.
310
+
311
+ ## Licence
312
+
313
+ `LICENSE` (MIT) covers everything in the repository and in the released
314
+ package: the code; the YAML under `data/`, which is the owner's
315
+ compilation of published opinions, recorded as printed; the claim table
316
+ generated from it; and `notes/`, the owner's and the assistant's writing.
317
+ If the corpus is useful in published work, please cite it
318
+ (`CITATION.cff`).
319
+
@@ -0,0 +1,297 @@
1
+ # Phylohist: Exploring changes in systematics over time
2
+
3
+ Science is always in motion. Most online taxonomy or phylogeny
4
+ databases attempt to show a consensus or accepted view, with
5
+ each site having its own editorial policy for what gets included.
6
+ Some include historical information, but do not make it a central
7
+ or easily-accessible part of the sysetm.
8
+
9
+ The `phylohist` project instead provides access to trees as published,
10
+ over time, while leaving the judgement of what to accept or reject to
11
+ the researcher. An LLM-driven interface supports complex queries over
12
+ a curated corpus stored as YAML data. This uses a model where one is
13
+ needed, and prioritizes reliability, reproducibility, speed,
14
+ and lower costs where one is not.
15
+
16
+ The current corpus holds over 200 papers entered in whole or in part, from
17
+ the mid-1700s to the present, mostly focusing on Paleozoic echinoderms.
18
+ A coverage system tracks how much of the information from a paper has
19
+ been entered and reviewed.
20
+
21
+ ## Status and future plans
22
+
23
+ This repository began as a place to store my notes, and gradually evolved
24
+ into a software package, featuring more and more modern software engineering
25
+ best practices as I have found time to add them. However, it remains
26
+ a solo, unfunded project that I work on whenever I can.
27
+
28
+ The package is published on PyPI as `phylohist` from version 0.1.0.
29
+ Next steps include writing human-user-friendly documentation,
30
+ continuing to improve the software development methodology, curating
31
+ additional data and adding more features.
32
+
33
+ A data model for capturing specimen information has recenlty been
34
+ designed but data entry for this area is in its infancy. Additional
35
+ areas of fuure work are proper support for cladograms (currently
36
+ allowed in the data but treated more-or-less like systematic trees)
37
+ and data visualization.
38
+
39
+ ## Corpus Scope and Editorial Curation Policy
40
+
41
+ Because `phylohist` relies on manual validation and a human-in-the-loop
42
+ workflow, data ingestion proceeds slowly to prioritize high fidelity
43
+ over unchecked volume.
44
+
45
+ No data is entered purely by AI. The data model has grown from my experience
46
+ of manually reading papers and figuring out how to work with the data as
47
+ it was published. Current LLMs are too eager to make things "work" rather
48
+ than step back and consider the user experience.
49
+
50
+ ### Intentional Scoping and Partial Entry
51
+
52
+ Data entry is guided by the target research scope, currently focusing primarily
53
+ on Paleozoic echinoderms and their relatives in the Ambulacrarian stem group.
54
+
55
+ * **Partial Ingestion:** For vast foundational texts such as Linnaeus’s
56
+ *Systema Naturae*, only the specific branches of interest to the active
57
+ dataset are entered.
58
+ * **Closed-World Boundaries:** The data model is being enhanced with ways
59
+ to indicate when data is complete by some metric. However, updating
60
+ the data with these fields is itself a large, ongoing project.
61
+
62
+ ### Archival Fidelity vs. Modern Interpretation
63
+
64
+ Tracking archaic, text-heavy literature (particularly pre-19th-century sources
65
+ written in informal prose) presents a unique archival challenge.
66
+
67
+ * **Philosophy:** The core directive of this corpus is to capture the published
68
+ author's opinions *as they published them*. However, no data model is
69
+ perfect, so `phylohist` attempts to get as close as possible while
70
+ capturing literal text and editorial reasoning to inform users of
71
+ possible discrepancies and inferences. Only ICZN-mandated
72
+ textual normalizations are performed. In more recently-entered data,
73
+ the original textual form is also captured (e.g. "Asterias caputmedusae"
74
+ vs "Aſterias Caput meduſæ"). The common use of only non-Latin names for
75
+ higher taxa in earlier publications introduces further difficulty, as
76
+ does the uneven introduction of ranks other than those first used by Linnaeus.
77
+ * **Continuous Ingestion:** Determining how to translate loose, informal
78
+ prose into deterministic YAML schemas without breaking historical context
79
+ is an ongoing design effort. Often, a paper will inspire a revision
80
+ to the data model, meaning that data entered at different times shows
81
+ different levels of completion. Older data may use less precise structures
82
+ that will eventually brought in line with the current design so that
83
+ the older structures can be dropped.
84
+
85
+ *The project welcomes feedback or additions to schemas and coverage maps
86
+ via GitHub issues. Please open an issue prior to working on a pull request
87
+ to ensure that the request will be well-received.*
88
+
89
+ ## Humans, Models, and Code
90
+
91
+ The internet has made a tremendous amount of information available,
92
+ but finding what you need and verifying its accuracy is a lot of work.
93
+ Humans have the deepest judgement for data curation, while models
94
+ handle flexible querying beyond what fixed database queries can provide.
95
+ Underneath it all, deterministic code ensures fast, repeatable, and
96
+ accurate outcomes.
97
+
98
+ This diagram shows the roles of humans (the top row), models (the middle)
99
+ and code. The third column shows the expected typical interactive usage,
100
+ where the model interprets the questions and chooses the tools to call and
101
+ output shapes to render, but leaves the querying and output construction
102
+ to code.
103
+
104
+ This avoids verbose or hallucinated output while spending tokens only
105
+ on the work that really requires a model's reasoning and flexibility.
106
+
107
+ <picture>
108
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/handrews/phylohist/main/docs/architecture-dark.svg">
109
+ <img alt="How phylohist fits together: three lanes, human, model and code, read in four columns, the data, the CLI, chat and the eval" src="https://raw.githubusercontent.com/handrews/phylohist/main/docs/architecture.svg">
110
+ </picture>
111
+
112
+ - **The data.** The curator records each publication's opinions as
113
+ printed: who published what systematic information in which paper.
114
+ That is names and nomenclatural acts, placements, usages and
115
+ synonymies, the specimens they rest on with their geological context,
116
+ and the page, plate and figure numbers that locate each of these. It
117
+ is not diagnoses, descriptions or a narration of the paper; a
118
+ researcher who wants those follows the citation to the paper itself.
119
+ The model's part is optional and reviewable: it reads a
120
+ paper against its tree and writes a review (`notes/reviews/`), or
121
+ drafts a tree (`drafts/`) that code validates and the researcher
122
+ audits before it enters `data/`. The human and the model review each
123
+ other's work; code checks both against the schema and regenerates the
124
+ claim table, which CI keeps current.
125
+ - **The CLI.** A question goes from the researcher to the tools with no
126
+ model in the lane: `phylohist history rhenopyrgus` renders the block.
127
+ - **Chat.** Claude asks the MCP server. The model resolves the
128
+ names and papers the question mentions and states a plan, the blocks
129
+ the answer is made of; code builds and renders them. The model
130
+ chooses; code answers. The only words of the model's own that reach a
131
+ reader are a one-line header stating the parameters it chose.
132
+ - **The eval.** The runner drives the model over the committed
133
+ questions in compose or planner mode, the grader is code, and a model
134
+ judges only the header. The researcher writes the questions and
135
+ reviews the grades and write-ups (`eval/`).
136
+
137
+ ## Correctness, Performance, and Cost
138
+
139
+ The project's evolution can be seen through the evaluation
140
+ [metrics](https://github.com/handrews/phylohist/blob/main/eval/findings/metrics.md).
141
+
142
+ Moving from AI-written prose answers to planned queries with modular
143
+ output blocks improved key measurements across complete evaluation runs:
144
+
145
+ * The measured pass rate rose from 61% to 87% on the original question
146
+ set, with several failure modes eliminated entirely; the latest run
147
+ (2026-11-02, the run version 0.1.0 ships with) passes 80% of those
148
+ questions and 80% of the expanded set of 56.
149
+ * Wall clock time was cut from around 25 minutes to around 10 minutes,
150
+ over a quarter more questions.
151
+ * Token usage dropped from 2.25 million to 0.60 million.
152
+
153
+ Future improvements to how the model selects blocks are expected to raise
154
+ the correctness score.
155
+
156
+ ## Tools and MCP
157
+
158
+ The `phylohist` CLI runs queries over the claims table generated from
159
+ the curated YAML data. These result in output data blocks rendered
160
+ as text, Markdown, or JSON based on the `--style` argument.
161
+
162
+ The CLI has one subcommand per tool:
163
+
164
+ poetry run phylohist resolve "Palæaster"
165
+ poetry run phylohist contents 1994_guensburg_sprinkle astrocystitidae --synonymy
166
+ poetry run phylohist descendants edrioblastoidea
167
+ poetry run phylohist ancestors astrocystitidae cyathocystidae rhenopyrgidae
168
+ poetry run phylohist history rhenopyrgus --style markdown
169
+ poetry run phylohist history "Rhenopyrgus grayae"
170
+ poetry run phylohist under rhenopyrgus edrioblastoidina
171
+ poetry run phylohist statements "Rhenopyrgus viviani"
172
+ poetry run phylohist gap "Holloway & Jell 1983" material
173
+ poetry run phylohist source "Lamarck 1816"
174
+ poetry run phylohist plan my-plan.yaml
175
+ poetry run python scripts/eval_run.py --mode planner --ask "Who first placed Rhenopyrgus under Edrioblastoidina?"
176
+
177
+ The same tools are served over MCP by the `phylohist-mcp` command
178
+ (`phylohist/mcp.py`), which `.mcp.json` registers for Claude Code:
179
+ a chat model can read blocks or state a plan and get the rendered answer.
180
+ The "Reading the table" section of `docs/claims.md` describes the blocks
181
+ and the tools.
182
+
183
+ ### Tool Examples
184
+
185
+ What one paper places in a family, showing only what the paper included:
186
+
187
+ $ poetry run phylohist contents 1994_guensburg_sprinkle astrocystitidae
188
+ Guensburg & Sprinkle 1994
189
+ Family Astrocystitidae emend.
190
+ Genus Astrocystites
191
+ Genus Cambroblastus
192
+ Genus Lampteroblastus gen. nov.
193
+ Type species. Lampteroblastus hintzei
194
+ Lampteroblastus hintzei sp. nov.
195
+
196
+ The emendation, the new genus and species, and the type species are the
197
+ paper's own statements; nothing here is inferred, and a source whose
198
+ listing is not yet entered says so instead.
199
+
200
+ See [`docs/walkthrough.md`](https://github.com/handrews/phylohist/blob/main/docs/walkthrough.md) for additional examples.
201
+
202
+ ### Asking from the CLI
203
+
204
+ The `eval_run.py` script can be used to ask a question without using the
205
+ chat interface to see how the model plans the queries and selects the output
206
+ blocks. It requires an Anthropic API key to be configured.
207
+
208
+ poetry run python scripts/eval_run.py --ask "Who first placed Rhenopyrgus under Edrioblastoidina?"
209
+
210
+ Rhenopyrgus (including its subgenus rank variant) placed under Edrioblastoidina (= Edrioblastoidea); taxonomy tree, all years
211
+
212
+ Rhenopyrgus Dehm 1961 under Edrioblastoidina Fay 1962: 4 papers, 4 co-author sets, 1994–2020
213
+ first Guensburg & Sprinkle 1994, last Ewin et al. 2020
214
+
215
+ 1994 Guensburg & Sprinkle Cyathocystidae › Rhenopyrginae › Rhenopyrgus
216
+ 2000 Grigo Cyathocystidae › Rhenopyrginae › Rhenopyrgus
217
+ 2013 Sumrall et al. Rhenopyrgidae › Rhenopyrgus
218
+ 2020 Ewin et al. Rhenopyrgidae › Rhenopyrgus
219
+
220
+ --- trail
221
+ resolve_name {"query": "Rhenopyrgus"} -> 2 candidate(s)
222
+ resolve_name {"query": "Edrioblastoidina"} -> 1 candidate(s)
223
+ placed_under {"record": "rhenopyrgus", "parent": "edrioblastoidina", "include_variants": true} -> 1 block(s)
224
+ header: Rhenopyrgus (including its subgenus rank variant) placed under Edrioblastoidina (= Edrioblastoidea); taxonomy tree, all years
225
+ 21227+375 tokens, 6.9s, tool_use
226
+
227
+ ## Install
228
+
229
+ From PyPI, for the tools and the MCP server over the claim table as of
230
+ the release (Python 3.12 or later):
231
+
232
+ pip install phylohist
233
+ phylohist history rhenopyrgus
234
+ phylohist-mcp
235
+
236
+ The second command is the server over stdio, which any MCP client runs
237
+ by name. For Claude Desktop or Claude Code the entry is
238
+
239
+ {"mcpServers": {"phylohist": {"command": "phylohist-mcp"}}}
240
+
241
+ or, with nothing installed, `uvx --from phylohist phylohist-mcp` as the
242
+ command and its arguments.
243
+
244
+ From a checkout, for the loader, the generator and the eval,
245
+ [Poetry](https://python-poetry.org/):
246
+
247
+ poetry install
248
+
249
+ The claim table the tools read is generated into `phylohist/table/`, so
250
+ a built package carries the table as of its build and a clone answers
251
+ from the table as `poetry run regenerate` last wrote it.
252
+ `PHYLOHIST_CLAIMS` names another table to read.
253
+
254
+ Only `scripts/eval_run.py` and the grader's `--judge` call a model;
255
+ their client is the `eval` dependency group, and they read
256
+ `ANTHROPIC_API_KEY` from the environment or from a git-ignored `.env` at
257
+ the repository root. Nothing else needs a key.
258
+
259
+ ## Checks
260
+
261
+ CI runs these on Python 3.12 and 3.14 and fails if the generated
262
+ schema census, the claim table or the expected-warnings file is stale;
263
+ after editing `data/` or the schema, `poetry run regenerate` rewrites all
264
+ three (a warning the load no longer produces leaves the file; a new one
265
+ is added with `scripts/expected_warnings.py --add`):
266
+
267
+ poetry run ruff check .
268
+ poetry run ruff format --check .
269
+ poetry run pytest --cov=phylohist --cov-fail-under=90
270
+ poetry run regenerate
271
+ git diff --exit-code scripts/schema-usage.md phylohist/table/ tests/expected-warnings.txt
272
+ poetry run python scripts/check_draft.py drafts/<file>.yaml
273
+
274
+ The tests run over the frozen copy of the data under `tests/corpus/`;
275
+ only those marked `production` load `data/` itself, so improving the
276
+ data cannot break a test of the code. `poetry run pytest --demo` adds the
277
+ eval questions and the walkthrough over the committed `phylohist/table/`, which
278
+ hold for the data they were last refreshed against.
279
+
280
+ ## Where things are
281
+
282
+ * `docs/` will contain user documentation; for now it explains how
283
+ recorded tree data is converted to the claims that the tools use,
284
+ as well as the tools and the answer formats.
285
+ * `notes/` contains project development information from both the human
286
+ and LLM developers; some of this information might be out-of-date.
287
+ * `eval/` holds the evaluation questions, results, write-ups, and metrics.
288
+ * `drafts/` holds AI-drafted trees awaiting a human audit.
289
+
290
+ ## Licence
291
+
292
+ `LICENSE` (MIT) covers everything in the repository and in the released
293
+ package: the code; the YAML under `data/`, which is the owner's
294
+ compilation of published opinions, recorded as printed; the claim table
295
+ generated from it; and `notes/`, the owner's and the assistant's writing.
296
+ If the corpus is useful in published work, please cite it
297
+ (`CITATION.cff`).
@@ -0,0 +1,31 @@
1
+ import copy
2
+ import logging
3
+ import os
4
+ import sys
5
+
6
+ import coloredlog
7
+
8
+
9
+ class ColourHandler(coloredlog.ConsoleHandler):
10
+ """`coloredlog` writes its colour codes into the record it is given, and
11
+ every handler after it then sees them: a collector comparing messages
12
+ with the expected warnings, pytest's caplog. This colours a copy."""
13
+
14
+ def emit(self, record):
15
+ super().emit(copy.copy(record))
16
+
17
+
18
+ _phylohist_logger = logging.getLogger(__name__)
19
+ _log_formatter = logging.Formatter(
20
+ '%(asctime)s %(filename)s:%(lineno)d [%(levelname)s] %(message)s',
21
+ )
22
+ _log_handler = (
23
+ ColourHandler(stream=sys.stderr)
24
+ if sys.stderr.isatty() or os.getenv('PHYLOHIST_COLOR') == '1'
25
+ else logging.StreamHandler()
26
+ )
27
+ _log_handler.setFormatter(_log_formatter)
28
+ _phylohist_logger.addHandler(_log_handler)
29
+ _phylohist_logger.setLevel(logging.INFO)
30
+
31
+ logger = _phylohist_logger