gapit 0.5.0__tar.gz → 0.5.2__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 (426) hide show
  1. {gapit-0.5.0 → gapit-0.5.2}/AGENTS.md +27 -18
  2. {gapit-0.5.0 → gapit-0.5.2}/CHANGELOG.md +158 -0
  3. {gapit-0.5.0 → gapit-0.5.2}/PKG-INFO +6 -5
  4. {gapit-0.5.0 → gapit-0.5.2}/README.md +5 -4
  5. {gapit-0.5.0 → gapit-0.5.2}/SPEC.md +6 -2
  6. {gapit-0.5.0 → gapit-0.5.2}/docs/agents.md +1 -1
  7. {gapit-0.5.0 → gapit-0.5.2}/docs/agents.zh.md +1 -1
  8. {gapit-0.5.0 → gapit-0.5.2}/docs/databases.md +93 -11
  9. {gapit-0.5.0 → gapit-0.5.2}/docs/databases.zh.md +84 -7
  10. {gapit-0.5.0 → gapit-0.5.2}/docs/faq.md +10 -7
  11. {gapit-0.5.0 → gapit-0.5.2}/docs/faq.zh.md +9 -7
  12. {gapit-0.5.0 → gapit-0.5.2}/docs/installation.md +2 -2
  13. {gapit-0.5.0 → gapit-0.5.2}/docs/installation.zh.md +2 -2
  14. {gapit-0.5.0 → gapit-0.5.2}/docs/mcp.md +4 -4
  15. {gapit-0.5.0 → gapit-0.5.2}/docs/mcp.zh.md +4 -4
  16. {gapit-0.5.0 → gapit-0.5.2}/docs/outputs.md +16 -12
  17. {gapit-0.5.0 → gapit-0.5.2}/docs/outputs.zh.md +16 -12
  18. {gapit-0.5.0 → gapit-0.5.2}/docs/quickstart.md +1 -1
  19. {gapit-0.5.0 → gapit-0.5.2}/docs/quickstart.zh.md +1 -1
  20. {gapit-0.5.0 → gapit-0.5.2}/docs/reads.md +199 -31
  21. {gapit-0.5.0 → gapit-0.5.2}/docs/reads.zh.md +187 -33
  22. {gapit-0.5.0 → gapit-0.5.2}/docs/screen.md +37 -12
  23. {gapit-0.5.0 → gapit-0.5.2}/docs/screen.zh.md +31 -12
  24. {gapit-0.5.0 → gapit-0.5.2}/docs/summary.md +51 -13
  25. {gapit-0.5.0 → gapit-0.5.2}/docs/summary.zh.md +45 -12
  26. {gapit-0.5.0 → gapit-0.5.2}/docs/typing.md +50 -10
  27. {gapit-0.5.0 → gapit-0.5.2}/docs/typing.zh.md +48 -10
  28. {gapit-0.5.0 → gapit-0.5.2}/pixi.lock +2 -2
  29. {gapit-0.5.0 → gapit-0.5.2}/pixi.toml +1 -1
  30. {gapit-0.5.0 → gapit-0.5.2}/pyproject.toml +1 -1
  31. {gapit-0.5.0 → gapit-0.5.2}/recipe/meta.yaml +3 -3
  32. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/__init__.py +1 -1
  33. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/bundled.py +10 -2
  34. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/cli.py +1 -1
  35. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/cmd_db_build.py +13 -0
  36. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/cmd_db_search.py +6 -1
  37. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/cmd_screen.py +86 -11
  38. gapit-0.5.2/src/gapit/cmd_screen_positionals.py +43 -0
  39. gapit-0.5.2/src/gapit/cmd_screen_reads_args.py +102 -0
  40. gapit-0.5.2/src/gapit/cmd_summary.py +125 -0
  41. gapit-0.5.2/src/gapit/data/dbs/ecoli_dec/floors.json +1 -0
  42. gapit-0.5.2/src/gapit/data/dbs/lm_doumith/bundled.json +7 -0
  43. gapit-0.5.2/src/gapit/data/dbs/lm_doumith/sequences +58 -0
  44. gapit-0.5.2/src/gapit/data/dbs/lm_doumith/typing.json +72 -0
  45. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/db_build_ops.py +18 -2
  46. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/formats/md.py +67 -26
  47. gapit-0.5.2/src/gapit/formats/reads_tsv.py +69 -0
  48. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/formats/schemas.py +2 -0
  49. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/formats/summary.py +15 -9
  50. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/formats/typing_result.py +27 -15
  51. gapit-0.5.2/src/gapit/gene_floors.py +122 -0
  52. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/mcp_tools.py +5 -11
  53. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/minimap2_run.py +7 -0
  54. gapit-0.5.2/src/gapit/readpairs.py +110 -0
  55. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/reads.py +14 -2
  56. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/screening_reads.py +41 -25
  57. gapit-0.5.2/src/gapit/screening_reads_positional.py +168 -0
  58. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/summary.py +60 -23
  59. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/typing_ops.py +5 -1
  60. gapit-0.5.2/tests/data/reads/s1_1.fq.gz +0 -0
  61. gapit-0.5.2/tests/data/reads/s1_2.fq.gz +0 -0
  62. gapit-0.5.2/tests/data/reads/s2_R1.fq.gz +0 -0
  63. gapit-0.5.2/tests/data/reads/s2_R2.fq.gz +0 -0
  64. gapit-0.5.2/tests/data/typing/schemes/lm_doumith.fa +58 -0
  65. gapit-0.5.2/tests/data/typing/schemes/lm_doumith.json +72 -0
  66. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/cluster_exact.json +1 -1
  67. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/cluster_exact.md +1 -1
  68. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/cluster_fragmented.json +1 -1
  69. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/cluster_fragmented.md +1 -1
  70. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/cluster_typing_ambiguous.json +1 -1
  71. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/cluster_typing_ambiguous.md +1 -1
  72. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/cluster_typing_cm_exact.json +1 -1
  73. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/cluster_typing_cm_exact.md +1 -1
  74. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/cluster_typing_exact.json +1 -1
  75. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/cluster_typing_exact.md +1 -1
  76. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/cluster_vc_inaba.json +1 -1
  77. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/cluster_vc_inaba.md +1 -1
  78. gapit-0.5.2/tests/golden/ecoli_dec_typing.tsv +5 -0
  79. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/fragments_merge.json +1 -1
  80. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/fragments_merge.md +1 -1
  81. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/gene_dec_pic_astA.json +1 -1
  82. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/gene_dec_pic_astA.md +1 -1
  83. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/gene_doumith_4b.json +1 -1
  84. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/gene_doumith_4b.md +1 -1
  85. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/gene_serotyping_l4b.json +1 -1
  86. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/gene_serotyping_l4b.md +1 -1
  87. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/gene_serotyping_mixed.json +1 -1
  88. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/gene_serotyping_mixed.md +1 -1
  89. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/gene_serotyping_vp_typed.json +1 -1
  90. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/gene_serotyping_vp_typed.md +1 -1
  91. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/gene_shigella_mixed.json +1 -1
  92. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/gene_shigella_mixed.md +1 -1
  93. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/gene_typing_exact.json +1 -1
  94. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/gene_typing_exact.md +1 -1
  95. gapit-0.5.2/tests/golden/lm_doumith_typing.tsv +3 -0
  96. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/reads_tinyamr.json +3 -3
  97. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/reads_tinyamr.md +2 -2
  98. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/screen_multi.json +1 -1
  99. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/screen_multi.md +1 -1
  100. gapit-0.5.2/tests/golden/summary_dutch.tsv +4 -0
  101. gapit-0.5.2/tests/golden/summary_multi.csv +3 -0
  102. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/summary_multi.json +1 -1
  103. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/summary_multi.md +4 -4
  104. gapit-0.5.2/tests/golden/summary_multi.tsv +4 -0
  105. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/typing_markers.json +17 -1
  106. gapit-0.5.2/tests/golden/typing_markers.md +20 -0
  107. gapit-0.5.2/tests/golden/typing_markers.tsv +7 -0
  108. gapit-0.5.2/tests/golden/typing_serotyping.tsv +21 -0
  109. {gapit-0.5.0 → gapit-0.5.2}/tests/parity/run_summary_parity.py +4 -4
  110. {gapit-0.5.0 → gapit-0.5.2}/tests/test_bundled.py +81 -25
  111. {gapit-0.5.0 → gapit-0.5.2}/tests/test_cli_aligner.py +50 -22
  112. {gapit-0.5.0 → gapit-0.5.2}/tests/test_cli_bare_help.py +7 -5
  113. {gapit-0.5.0 → gapit-0.5.2}/tests/test_cli_db_build.py +98 -0
  114. {gapit-0.5.0 → gapit-0.5.2}/tests/test_cli_db_fetch.py +2 -0
  115. {gapit-0.5.0 → gapit-0.5.2}/tests/test_cli_reads.py +97 -23
  116. {gapit-0.5.0 → gapit-0.5.2}/tests/test_cli_reads2.py +38 -13
  117. gapit-0.5.2/tests/test_cli_reads_glob.py +311 -0
  118. gapit-0.5.2/tests/test_cli_reads_glob_jobs.py +437 -0
  119. {gapit-0.5.0 → gapit-0.5.2}/tests/test_cli_schema.py +11 -0
  120. {gapit-0.5.0 → gapit-0.5.2}/tests/test_cli_setupdb.py +8 -5
  121. {gapit-0.5.0 → gapit-0.5.2}/tests/test_cli_short_options.py +115 -13
  122. gapit-0.5.2/tests/test_cli_summary.py +351 -0
  123. {gapit-0.5.0 → gapit-0.5.2}/tests/test_db_list_extras.py +2 -1
  124. {gapit-0.5.0 → gapit-0.5.2}/tests/test_gapit_db_e2e.py +12 -2
  125. gapit-0.5.2/tests/test_gene_floors.py +244 -0
  126. gapit-0.5.2/tests/test_gene_floors_e2e.py +144 -0
  127. {gapit-0.5.0 → gapit-0.5.2}/tests/test_gene_typing.py +21 -14
  128. {gapit-0.5.0 → gapit-0.5.2}/tests/test_gene_typing2.py +1 -1
  129. gapit-0.5.2/tests/test_lm_doumith.py +313 -0
  130. gapit-0.5.2/tests/test_readpairs.py +210 -0
  131. {gapit-0.5.0 → gapit-0.5.2}/tests/test_reads2_homologs.py +2 -0
  132. {gapit-0.5.0 → gapit-0.5.2}/tests/test_reads_streaming.py +2 -2
  133. {gapit-0.5.0 → gapit-0.5.2}/tests/test_screening_reads_unit.py +29 -3
  134. {gapit-0.5.0 → gapit-0.5.2}/tests/test_summary_formats.py +5 -5
  135. {gapit-0.5.0 → gapit-0.5.2}/tests/test_typing_command.py +8 -2
  136. gapit-0.5.0/src/gapit/cmd_screen_reads_args.py +0 -38
  137. gapit-0.5.0/src/gapit/cmd_summary.py +0 -67
  138. gapit-0.5.0/tests/golden/ecoli_dec_typing.tsv +0 -5
  139. gapit-0.5.0/tests/golden/summary_dutch.tsv +0 -4
  140. gapit-0.5.0/tests/golden/summary_multi.csv +0 -3
  141. gapit-0.5.0/tests/golden/summary_multi.tsv +0 -4
  142. gapit-0.5.0/tests/golden/typing_markers.md +0 -20
  143. gapit-0.5.0/tests/golden/typing_markers.tsv +0 -7
  144. gapit-0.5.0/tests/golden/typing_serotyping.tsv +0 -21
  145. gapit-0.5.0/tests/test_cli_summary.py +0 -203
  146. {gapit-0.5.0 → gapit-0.5.2}/.gitattributes +0 -0
  147. {gapit-0.5.0 → gapit-0.5.2}/.github/workflows/ci.yml +0 -0
  148. {gapit-0.5.0 → gapit-0.5.2}/.github/workflows/docs.yml +0 -0
  149. {gapit-0.5.0 → gapit-0.5.2}/.github/workflows/release.yml +0 -0
  150. {gapit-0.5.0 → gapit-0.5.2}/.gitignore +0 -0
  151. {gapit-0.5.0 → gapit-0.5.2}/LICENSE +0 -0
  152. {gapit-0.5.0 → gapit-0.5.2}/PLAN.md +0 -0
  153. {gapit-0.5.0 → gapit-0.5.2}/docs/custom-db.md +0 -0
  154. {gapit-0.5.0 → gapit-0.5.2}/docs/custom-db.zh.md +0 -0
  155. {gapit-0.5.0 → gapit-0.5.2}/docs/index.md +0 -0
  156. {gapit-0.5.0 → gapit-0.5.2}/docs/index.zh.md +0 -0
  157. {gapit-0.5.0 → gapit-0.5.2}/mkdocs.yml +0 -0
  158. {gapit-0.5.0 → gapit-0.5.2}/scripts/cluster_calibration.py +0 -0
  159. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/blast.py +0 -0
  160. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/cluster.py +0 -0
  161. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/cluster_math.py +0 -0
  162. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/clusterbuild.py +0 -0
  163. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/cmd_db.py +0 -0
  164. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/cmd_db_install.py +0 -0
  165. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/cmd_db_outdated.py +0 -0
  166. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/cmd_typing.py +0 -0
  167. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/config.py +0 -0
  168. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/data/dbs/ecoh/bundled.json +0 -0
  169. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/data/dbs/ecoh/sequences +0 -0
  170. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/data/dbs/ecoli_dec/bundled.json +0 -0
  171. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/data/dbs/ecoli_dec/sequences +0 -0
  172. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/data/dbs/ecoli_dec/typing.json +0 -0
  173. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/data/dbs/ncbi/bundled.json +0 -0
  174. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/data/dbs/ncbi/sequences +0 -0
  175. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/data/dbs/resfinder/bundled.json +0 -0
  176. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/data/dbs/resfinder/sequences +0 -0
  177. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/data/dbs/upec_expec_vf/bundled.json +0 -0
  178. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/data/dbs/upec_expec_vf/sequences +0 -0
  179. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/db.py +0 -0
  180. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/db_ops.py +0 -0
  181. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/db_query_ops.py +0 -0
  182. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/dbbuild.py +0 -0
  183. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/dbcodec.py +0 -0
  184. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/dispatch.py +0 -0
  185. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/engines.py +0 -0
  186. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/errors.py +0 -0
  187. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/fasta.py +0 -0
  188. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/formats/__init__.py +0 -0
  189. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/formats/cluster.py +0 -0
  190. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/formats/cluster_md.py +0 -0
  191. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/formats/json.py +0 -0
  192. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/formats/reads_json.py +0 -0
  193. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/formats/tsv.py +0 -0
  194. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/fragments.py +0 -0
  195. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/gbfeatures.py +0 -0
  196. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/gffparse.py +0 -0
  197. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/hits.py +0 -0
  198. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/mcp.py +0 -0
  199. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/mcp_schemas.py +0 -0
  200. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/minimap.py +0 -0
  201. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/paf.py +0 -0
  202. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/proctools.py +0 -0
  203. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/providers/__init__.py +0 -0
  204. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/providers/ab_k.py +0 -0
  205. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/providers/ab_o.py +0 -0
  206. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/providers/argannot.py +0 -0
  207. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/providers/bacmet2.py +0 -0
  208. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/providers/card.py +0 -0
  209. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/providers/cluster_common.py +0 -0
  210. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/providers/common.py +0 -0
  211. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/providers/ecoh.py +0 -0
  212. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/providers/ecoli_kps.py +0 -0
  213. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/providers/ecoli_vf.py +0 -0
  214. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/providers/kosc_k.py +0 -0
  215. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/providers/kosc_o.py +0 -0
  216. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/providers/kpsc_k.py +0 -0
  217. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/providers/kpsc_o.py +0 -0
  218. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/providers/megares.py +0 -0
  219. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/providers/ncbi.py +0 -0
  220. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/providers/plasmidfinder.py +0 -0
  221. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/providers/resfinder.py +0 -0
  222. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/providers/upec_expec_vf.py +0 -0
  223. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/providers/vfdb.py +0 -0
  224. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/providers/victors.py +0 -0
  225. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/py.typed +0 -0
  226. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/records.py +0 -0
  227. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/report.py +0 -0
  228. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/screening.py +0 -0
  229. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/screening_cluster.py +0 -0
  230. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/seqconvert.py +0 -0
  231. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/typing_decide.py +0 -0
  232. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/typing_engine.py +0 -0
  233. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/typing_gene.py +0 -0
  234. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/typing_input.py +0 -0
  235. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/typing_models.py +0 -0
  236. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/typing_results.py +0 -0
  237. {gapit-0.5.0 → gapit-0.5.2}/src/gapit/typing_rules.py +0 -0
  238. {gapit-0.5.0 → gapit-0.5.2}/tests/data/bundled_differential/resfinder/HEAD.zip +0 -0
  239. {gapit-0.5.0 → gapit-0.5.2}/tests/data/bundled_differential/resfinder/README.md +0 -0
  240. {gapit-0.5.0 → gapit-0.5.2}/tests/data/cluster/bakta_style.gbk +0 -0
  241. {gapit-0.5.0 → gapit-0.5.2}/tests/data/cluster/clusters.gff3 +0 -0
  242. {gapit-0.5.0 → gapit-0.5.2}/tests/data/cluster/clusters_gz.gff3.gz +0 -0
  243. {gapit-0.5.0 → gapit-0.5.2}/tests/data/cluster/clusters_sidecar.fa +0 -0
  244. {gapit-0.5.0 → gapit-0.5.2}/tests/data/cluster/clusters_sidecar.gff3 +0 -0
  245. {gapit-0.5.0 → gapit-0.5.2}/tests/data/cluster/compound.gbk +0 -0
  246. {gapit-0.5.0 → gapit-0.5.2}/tests/data/cluster/gz_input.gbk.gz +0 -0
  247. {gapit-0.5.0 → gapit-0.5.2}/tests/data/cluster/kaptive_style.gbk +0 -0
  248. {gapit-0.5.0 → gapit-0.5.2}/tests/data/cluster/nofasta.gff3 +0 -0
  249. {gapit-0.5.0 → gapit-0.5.2}/tests/data/cluster/screening.gbk +0 -0
  250. {gapit-0.5.0 → gapit-0.5.2}/tests/data/cluster/typing_invalid.json +0 -0
  251. {gapit-0.5.0 → gapit-0.5.2}/tests/data/cluster/typing_screen.json +0 -0
  252. {gapit-0.5.0 → gapit-0.5.2}/tests/data/cluster/typing_screen_cm.json +0 -0
  253. {gapit-0.5.0 → gapit-0.5.2}/tests/data/cluster/typing_screen_v2.json +0 -0
  254. {gapit-0.5.0 → gapit-0.5.2}/tests/data/cluster/typing_valid.json +0 -0
  255. {gapit-0.5.0 → gapit-0.5.2}/tests/data/cluster/unnamed_cds.gbk +0 -0
  256. {gapit-0.5.0 → gapit-0.5.2}/tests/data/contigs/full.fa +0 -0
  257. {gapit-0.5.0 → gapit-0.5.2}/tests/data/contigs/gap.fa +0 -0
  258. {gapit-0.5.0 → gapit-0.5.2}/tests/data/contigs/none.fa +0 -0
  259. {gapit-0.5.0 → gapit-0.5.2}/tests/data/contigs/partial.fa +0 -0
  260. {gapit-0.5.0 → gapit-0.5.2}/tests/data/contigs/sort.fa +0 -0
  261. {gapit-0.5.0 → gapit-0.5.2}/tests/data/convert/sample.embl +0 -0
  262. {gapit-0.5.0 → gapit-0.5.2}/tests/data/convert/sample.embl.bz2 +0 -0
  263. {gapit-0.5.0 → gapit-0.5.2}/tests/data/convert/sample.fa +0 -0
  264. {gapit-0.5.0 → gapit-0.5.2}/tests/data/convert/sample.fa.gz +0 -0
  265. {gapit-0.5.0 → gapit-0.5.2}/tests/data/convert/sample.fq +0 -0
  266. {gapit-0.5.0 → gapit-0.5.2}/tests/data/convert/sample.gbk +0 -0
  267. {gapit-0.5.0 → gapit-0.5.2}/tests/data/convert/sample.gbk.gz +0 -0
  268. {gapit-0.5.0 → gapit-0.5.2}/tests/data/db/tinyamr/sequences +0 -0
  269. {gapit-0.5.0 → gapit-0.5.2}/tests/data/fragments/fragdb/sequences +0 -0
  270. {gapit-0.5.0 → gapit-0.5.2}/tests/data/fragments/split3040.fa +0 -0
  271. {gapit-0.5.0 → gapit-0.5.2}/tests/data/fragments/split4060.fa +0 -0
  272. {gapit-0.5.0 → gapit-0.5.2}/tests/data/fragments/split5050.fa +0 -0
  273. {gapit-0.5.0 → gapit-0.5.2}/tests/data/providers/argannot/ARG-ANNOT_NT_V6_July2019.txt +0 -0
  274. {gapit-0.5.0 → gapit-0.5.2}/tests/data/providers/bacmet2/BacMet2_EXP_database.fasta +0 -0
  275. {gapit-0.5.0 → gapit-0.5.2}/tests/data/providers/card/card.json +0 -0
  276. {gapit-0.5.0 → gapit-0.5.2}/tests/data/providers/ecoh/EcOH.fasta +0 -0
  277. {gapit-0.5.0 → gapit-0.5.2}/tests/data/providers/ecoli_vf/repaired_ecoli_vfs_shortnames.ffn +0 -0
  278. {gapit-0.5.0 → gapit-0.5.2}/tests/data/providers/megares/megares_drugs_demo.fasta +0 -0
  279. {gapit-0.5.0 → gapit-0.5.2}/tests/data/providers/ncbi/AMR_CDS.fa +0 -0
  280. {gapit-0.5.0 → gapit-0.5.2}/tests/data/providers/ncbi/ReferenceGeneCatalog.txt +0 -0
  281. {gapit-0.5.0 → gapit-0.5.2}/tests/data/providers/plasmidfinder/plasmids_a.fsa +0 -0
  282. {gapit-0.5.0 → gapit-0.5.2}/tests/data/providers/plasmidfinder/plasmids_b.fsa +0 -0
  283. {gapit-0.5.0 → gapit-0.5.2}/tests/data/providers/resfinder/aminoglycoside.fsa +0 -0
  284. {gapit-0.5.0 → gapit-0.5.2}/tests/data/providers/resfinder/beta-lactam.fsa +0 -0
  285. {gapit-0.5.0 → gapit-0.5.2}/tests/data/providers/resfinder/phenotypes.txt +0 -0
  286. {gapit-0.5.0 → gapit-0.5.2}/tests/data/providers/upec_expec_vf/UPEC_ExPEC_VF.tsv +0 -0
  287. {gapit-0.5.0 → gapit-0.5.2}/tests/data/providers/vfdb/VFDB_setA_nt.fas +0 -0
  288. {gapit-0.5.0 → gapit-0.5.2}/tests/data/providers/victors/gen_downloads.php +0 -0
  289. {gapit-0.5.0 → gapit-0.5.2}/tests/data/providers/victors/gen_downloads_protein.php +0 -0
  290. {gapit-0.5.0 → gapit-0.5.2}/tests/data/reads/bla_partial.fq +0 -0
  291. {gapit-0.5.0 → gapit-0.5.2}/tests/data/reads/junk.fq +0 -0
  292. {gapit-0.5.0 → gapit-0.5.2}/tests/data/reads/suly_partial.fq +0 -0
  293. {gapit-0.5.0 → gapit-0.5.2}/tests/data/reads/tetx_R1.fq +0 -0
  294. {gapit-0.5.0 → gapit-0.5.2}/tests/data/reads/tetx_R2.fq +0 -0
  295. {gapit-0.5.0 → gapit-0.5.2}/tests/data/reads/tetx_full.fq +0 -0
  296. {gapit-0.5.0 → gapit-0.5.2}/tests/data/reads/tetx_full.fq.gz +0 -0
  297. {gapit-0.5.0 → gapit-0.5.2}/tests/data/reads/tetx_lane1.fq +0 -0
  298. {gapit-0.5.0 → gapit-0.5.2}/tests/data/reads/tetx_lane2.fq +0 -0
  299. {gapit-0.5.0 → gapit-0.5.2}/tests/data/reads/tetx_pe1_R1.fq +0 -0
  300. {gapit-0.5.0 → gapit-0.5.2}/tests/data/reads/tetx_pe1_R2.fq +0 -0
  301. {gapit-0.5.0 → gapit-0.5.2}/tests/data/reads/tetx_pe2_R1.fq +0 -0
  302. {gapit-0.5.0 → gapit-0.5.2}/tests/data/reads/tetx_pe2_R2.fq +0 -0
  303. {gapit-0.5.0 → gapit-0.5.2}/tests/data/reads2/ont_homologs.fq +0 -0
  304. {gapit-0.5.0 → gapit-0.5.2}/tests/data/reads2/sr_homologs.fq +0 -0
  305. {gapit-0.5.0 → gapit-0.5.2}/tests/data/reads2_db/homologs/sequences +0 -0
  306. {gapit-0.5.0 → gapit-0.5.2}/tests/data/reads_db/tinyreads/sequences +0 -0
  307. {gapit-0.5.0 → gapit-0.5.2}/tests/data/summary/empty.tsv +0 -0
  308. {gapit-0.5.0 → gapit-0.5.2}/tests/data/summary/multi_sample.tsv +0 -0
  309. {gapit-0.5.0 → gapit-0.5.2}/tests/data/summary/sample_a.csv +0 -0
  310. {gapit-0.5.0 → gapit-0.5.2}/tests/data/summary/sample_a.tsv +0 -0
  311. {gapit-0.5.0 → gapit-0.5.2}/tests/data/summary/sample_b.csv +0 -0
  312. {gapit-0.5.0 → gapit-0.5.2}/tests/data/summary/sample_b.tsv +0 -0
  313. {gapit-0.5.0 → gapit-0.5.2}/tests/data/typing/dec_s1_aggR_pic_uidA.fasta +0 -0
  314. {gapit-0.5.0 → gapit-0.5.2}/tests/data/typing/dec_s2_pic_astA_uidA.fasta +0 -0
  315. {gapit-0.5.0 → gapit-0.5.2}/tests/data/typing/dec_s3_stx2a_escV_aggR_uidA.fasta +0 -0
  316. {gapit-0.5.0 → gapit-0.5.2}/tests/data/typing/exact.fa +0 -0
  317. {gapit-0.5.0 → gapit-0.5.2}/tests/data/typing/listeria_1c.fa +0 -0
  318. {gapit-0.5.0 → gapit-0.5.2}/tests/data/typing/listeria_4b.fa +0 -0
  319. {gapit-0.5.0 → gapit-0.5.2}/tests/data/typing/listeria_nogate.fa +0 -0
  320. {gapit-0.5.0 → gapit-0.5.2}/tests/data/typing/markers.fa +0 -0
  321. {gapit-0.5.0 → gapit-0.5.2}/tests/data/typing/mutated.fa +0 -0
  322. {gapit-0.5.0 → gapit-0.5.2}/tests/data/typing/negative.fa +0 -0
  323. {gapit-0.5.0 → gapit-0.5.2}/tests/data/typing/partial.fa +0 -0
  324. {gapit-0.5.0 → gapit-0.5.2}/tests/data/typing/schemes/cholerae.gbk +0 -0
  325. {gapit-0.5.0 → gapit-0.5.2}/tests/data/typing/schemes/cholerae.json +0 -0
  326. {gapit-0.5.0 → gapit-0.5.2}/tests/data/typing/schemes/dec.fa +0 -0
  327. {gapit-0.5.0 → gapit-0.5.2}/tests/data/typing/schemes/dec.json +0 -0
  328. {gapit-0.5.0 → gapit-0.5.2}/tests/data/typing/schemes/doumith.fa +0 -0
  329. {gapit-0.5.0 → gapit-0.5.2}/tests/data/typing/schemes/doumith.json +0 -0
  330. {gapit-0.5.0 → gapit-0.5.2}/tests/data/typing/schemes/meningotype.fa +0 -0
  331. {gapit-0.5.0 → gapit-0.5.2}/tests/data/typing/schemes/meningotype.json +0 -0
  332. {gapit-0.5.0 → gapit-0.5.2}/tests/data/typing/schemes/shigella.fa +0 -0
  333. {gapit-0.5.0 → gapit-0.5.2}/tests/data/typing/schemes/shigella.json +0 -0
  334. {gapit-0.5.0 → gapit-0.5.2}/tests/data/typing/schemes/vp_ok.gbk +0 -0
  335. {gapit-0.5.0 → gapit-0.5.2}/tests/data/typing/schemes/vp_ok.json +0 -0
  336. {gapit-0.5.0 → gapit-0.5.2}/tests/data/typing/serotyping.fa +0 -0
  337. {gapit-0.5.0 → gapit-0.5.2}/tests/data/typing/typing_markers_v1.json +0 -0
  338. {gapit-0.5.0 → gapit-0.5.2}/tests/data/typing/typing_markers_v2.json +0 -0
  339. {gapit-0.5.0 → gapit-0.5.2}/tests/data/typing/typing_serotyping_v2.json +0 -0
  340. {gapit-0.5.0 → gapit-0.5.2}/tests/data/typing/vp_mixed.fa +0 -0
  341. {gapit-0.5.0 → gapit-0.5.2}/tests/data/typing/vp_typed.fa +0 -0
  342. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/cluster_exact.tsv +0 -0
  343. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/cluster_fragmented.tsv +0 -0
  344. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/cluster_typing_ambiguous.tsv +0 -0
  345. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/cluster_typing_cm_exact.tsv +0 -0
  346. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/cluster_typing_exact.tsv +0 -0
  347. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/cluster_vc_inaba.tsv +0 -0
  348. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/ecoli_dec_typed.tsv +0 -0
  349. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/fragments_merge.tsv +0 -0
  350. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/tinyamr_multi_nopath.csv +0 -0
  351. {gapit-0.5.0 → gapit-0.5.2}/tests/golden/tinyamr_multi_nopath.tsv +0 -0
  352. {gapit-0.5.0 → gapit-0.5.2}/tests/parity/corpus/01_exact_and_junk.fa +0 -0
  353. {gapit-0.5.0 → gapit-0.5.2}/tests/parity/corpus/02_mutated.fa +0 -0
  354. {gapit-0.5.0 → gapit-0.5.2}/tests/parity/corpus/03_truncated.fa +0 -0
  355. {gapit-0.5.0 → gapit-0.5.2}/tests/parity/corpus/04_reverse.fa +0 -0
  356. {gapit-0.5.0 → gapit-0.5.2}/tests/parity/corpus/05_threshold.fa +0 -0
  357. {gapit-0.5.0 → gapit-0.5.2}/tests/parity/make_corpus.py +0 -0
  358. {gapit-0.5.0 → gapit-0.5.2}/tests/parity/run_parity.py +0 -0
  359. {gapit-0.5.0 → gapit-0.5.2}/tests/test_blast_parse.py +0 -0
  360. {gapit-0.5.0 → gapit-0.5.2}/tests/test_blast_pipeline.py +0 -0
  361. {gapit-0.5.0 → gapit-0.5.2}/tests/test_cli_completion.py +0 -0
  362. {gapit-0.5.0 → gapit-0.5.2}/tests/test_cli_db_build_cluster.py +0 -0
  363. {gapit-0.5.0 → gapit-0.5.2}/tests/test_cli_db_query.py +0 -0
  364. {gapit-0.5.0 → gapit-0.5.2}/tests/test_cli_fragments.py +0 -0
  365. {gapit-0.5.0 → gapit-0.5.2}/tests/test_cli_screen.py +0 -0
  366. {gapit-0.5.0 → gapit-0.5.2}/tests/test_cli_screen_jobs.py +0 -0
  367. {gapit-0.5.0 → gapit-0.5.2}/tests/test_cluster_calibration.py +0 -0
  368. {gapit-0.5.0 → gapit-0.5.2}/tests/test_cluster_db.py +0 -0
  369. {gapit-0.5.0 → gapit-0.5.2}/tests/test_cluster_math.py +0 -0
  370. {gapit-0.5.0 → gapit-0.5.2}/tests/test_cluster_screen.py +0 -0
  371. {gapit-0.5.0 → gapit-0.5.2}/tests/test_cluster_typing.py +0 -0
  372. {gapit-0.5.0 → gapit-0.5.2}/tests/test_config.py +0 -0
  373. {gapit-0.5.0 → gapit-0.5.2}/tests/test_db.py +0 -0
  374. {gapit-0.5.0 → gapit-0.5.2}/tests/test_db_fetch.py +0 -0
  375. {gapit-0.5.0 → gapit-0.5.2}/tests/test_db_headers.py +0 -0
  376. {gapit-0.5.0 → gapit-0.5.2}/tests/test_dbbuild.py +0 -0
  377. {gapit-0.5.0 → gapit-0.5.2}/tests/test_dbcodec.py +0 -0
  378. {gapit-0.5.0 → gapit-0.5.2}/tests/test_error_envelope.py +0 -0
  379. {gapit-0.5.0 → gapit-0.5.2}/tests/test_fasta.py +0 -0
  380. {gapit-0.5.0 → gapit-0.5.2}/tests/test_fragments.py +0 -0
  381. {gapit-0.5.0 → gapit-0.5.2}/tests/test_gbfeatures.py +0 -0
  382. {gapit-0.5.0 → gapit-0.5.2}/tests/test_gffparse.py +0 -0
  383. {gapit-0.5.0 → gapit-0.5.2}/tests/test_hits.py +0 -0
  384. {gapit-0.5.0 → gapit-0.5.2}/tests/test_json_format.py +0 -0
  385. {gapit-0.5.0 → gapit-0.5.2}/tests/test_mcp.py +0 -0
  386. {gapit-0.5.0 → gapit-0.5.2}/tests/test_mcp_db_tools.py +0 -0
  387. {gapit-0.5.0 → gapit-0.5.2}/tests/test_mcp_protocol.py +0 -0
  388. {gapit-0.5.0 → gapit-0.5.2}/tests/test_mcp_reads.py +0 -0
  389. {gapit-0.5.0 → gapit-0.5.2}/tests/test_md_format.py +0 -0
  390. {gapit-0.5.0 → gapit-0.5.2}/tests/test_minimap.py +0 -0
  391. {gapit-0.5.0 → gapit-0.5.2}/tests/test_mol_type.py +0 -0
  392. {gapit-0.5.0 → gapit-0.5.2}/tests/test_oversubscription.py +0 -0
  393. {gapit-0.5.0 → gapit-0.5.2}/tests/test_paf.py +0 -0
  394. {gapit-0.5.0 → gapit-0.5.2}/tests/test_paf_identity.py +0 -0
  395. {gapit-0.5.0 → gapit-0.5.2}/tests/test_provider_argannot.py +0 -0
  396. {gapit-0.5.0 → gapit-0.5.2}/tests/test_provider_bacmet2.py +0 -0
  397. {gapit-0.5.0 → gapit-0.5.2}/tests/test_provider_card.py +0 -0
  398. {gapit-0.5.0 → gapit-0.5.2}/tests/test_provider_ecoh.py +0 -0
  399. {gapit-0.5.0 → gapit-0.5.2}/tests/test_provider_ecoli_vf.py +0 -0
  400. {gapit-0.5.0 → gapit-0.5.2}/tests/test_provider_kaptive.py +0 -0
  401. {gapit-0.5.0 → gapit-0.5.2}/tests/test_provider_megares.py +0 -0
  402. {gapit-0.5.0 → gapit-0.5.2}/tests/test_provider_ncbi.py +0 -0
  403. {gapit-0.5.0 → gapit-0.5.2}/tests/test_provider_plasmidfinder.py +0 -0
  404. {gapit-0.5.0 → gapit-0.5.2}/tests/test_provider_resfinder.py +0 -0
  405. {gapit-0.5.0 → gapit-0.5.2}/tests/test_provider_upec_expec_vf.py +0 -0
  406. {gapit-0.5.0 → gapit-0.5.2}/tests/test_provider_vfdb.py +0 -0
  407. {gapit-0.5.0 → gapit-0.5.2}/tests/test_provider_victors.py +0 -0
  408. {gapit-0.5.0 → gapit-0.5.2}/tests/test_providers_common.py +0 -0
  409. {gapit-0.5.0 → gapit-0.5.2}/tests/test_reads2_model.py +0 -0
  410. {gapit-0.5.0 → gapit-0.5.2}/tests/test_reads_aggregate.py +0 -0
  411. {gapit-0.5.0 → gapit-0.5.2}/tests/test_reads_integration.py +0 -0
  412. {gapit-0.5.0 → gapit-0.5.2}/tests/test_reads_interval_union.py +0 -0
  413. {gapit-0.5.0 → gapit-0.5.2}/tests/test_records.py +0 -0
  414. {gapit-0.5.0 → gapit-0.5.2}/tests/test_report.py +0 -0
  415. {gapit-0.5.0 → gapit-0.5.2}/tests/test_screen_integration.py +0 -0
  416. {gapit-0.5.0 → gapit-0.5.2}/tests/test_seqconvert.py +0 -0
  417. {gapit-0.5.0 → gapit-0.5.2}/tests/test_seqconvert_differential.py +0 -0
  418. {gapit-0.5.0 → gapit-0.5.2}/tests/test_streaming_chunks.py +0 -0
  419. {gapit-0.5.0 → gapit-0.5.2}/tests/test_summary.py +0 -0
  420. {gapit-0.5.0 → gapit-0.5.2}/tests/test_tsv.py +0 -0
  421. {gapit-0.5.0 → gapit-0.5.2}/tests/test_typing_engine.py +0 -0
  422. {gapit-0.5.0 → gapit-0.5.2}/tests/test_typing_models.py +0 -0
  423. {gapit-0.5.0 → gapit-0.5.2}/tests/test_typing_schemes.py +0 -0
  424. {gapit-0.5.0 → gapit-0.5.2}/tests/test_typing_schemes_cluster.py +0 -0
  425. {gapit-0.5.0 → gapit-0.5.2}/tests/test_typing_stage2.py +0 -0
  426. {gapit-0.5.0 → gapit-0.5.2}/tests/test_version.py +0 -0
@@ -1,15 +1,18 @@
1
1
  # AGENTS.md — gapit
2
2
 
3
- > Python reimplementation of [abricate](https://github.com/tseemann/abricate): mass screening of
4
- > contigs and reads for known genes. **Agent-first**: every output is
5
- > machine-readable (JSON / Markdown) by design, not as an afterthought.
3
+ > Python tool for mass screening of contigs and reads for known genes, with gene-cluster
4
+ > typing and phenotype designation. Originally a reimplementation of
5
+ > [abricate](https://github.com/tseemann/abricate); **from v0.5.0 onward gapit pursues its
6
+ > own contract** — abricate parity is no longer a design goal. **Agent-first**: every
7
+ > output is machine-readable (JSON / Markdown) by design, not as an afterthought.
6
8
 
7
9
  ## 1. Mission
8
10
 
9
11
  `gapit` answers one question: **which known genes are present in this assembly, and how confident
10
- are we?** It replaces abricate (Perl) with a modern, typed, testable Python tool that:
12
+ are we?** A modern, typed, testable Python tool that:
11
13
 
12
- 1. Produces byte-compatible TSV with abricate (drop-in replacement for existing pipelines).
14
+ 1. Ships an abricate-compatible contig TSV as the historical baseline surface (frozen
15
+ behavior, kept for existing pipelines), while new development follows gapit's own design.
13
16
  2. Adds first-class **JSON** and **Markdown** outputs so LLM agents and humans can consume
14
17
  results without parsing tab-delimited text.
15
18
  3. Exposes stable, versioned output contracts (schemas, exit codes, error envelopes) that
@@ -52,7 +55,7 @@ Every change must leave `lint`, `typecheck`, and `test` green.
52
55
  gapit/
53
56
  ├── AGENTS.md # this file
54
57
  ├── PLAN.md # development roadmap (phase-gated)
55
- ├── SPEC.md # distilled abricate behavior spec (source of truth for parity)
58
+ ├── SPEC.md # frozen contract for the baseline surface (distilled from abricate)
56
59
  ├── pixi.toml
57
60
  ├── recipe/
58
61
  │ └── meta.yaml # conda recipe (submission deferred)
@@ -77,6 +80,7 @@ gapit/
77
80
  │ ├── db_query_ops.py # db use-cases: search + outdated over installed DBs (shared CLI + MCP)
78
81
  │ ├── db_build_ops.py # db use-case: custom FASTA+TSV → gene db, GBK/GFF → cluster db (shared CLI + MCP)
79
82
  │ ├── gbfeatures.py # GenBank FEATURES/ORIGIN parser → LocusFeatures/GeneFeature + gapit.features/1
83
+ │ ├── gene_floors.py # gapit.floors/1 per-gene identity floors: model, loader, build validation, reads gate
80
84
  │ ├── gffparse.py # GFF3 parser (embedded ##FASTA or sidecar) → the same locus/gene models
81
85
  │ ├── typing_models.py # gapit.typing schema (rules + named schemes; /1 degrades to one default scheme)
82
86
  │ ├── typing_rules.py # gapit.typing rule models (weighted_genes/exact_set/cluster_match/learned_linear) + reference checks
@@ -101,6 +105,7 @@ gapit/
101
105
  │ ├── reads.py # FASTQ mode: minimap2 PAF parsing, coverage breadth/depth, presence
102
106
  │ ├── summary.py # summary core: parse report tables into a gene matrix
103
107
  │ ├── cmd_screen.py # `gapit screen` CLI (registered from cli.py)
108
+ │ ├── cmd_screen_positionals.py # screen positional guard: db-name-as-file usage error
104
109
  │ ├── cmd_screen_reads_args.py # reads-mode CLI arg rules (comma split + flag rejects)
105
110
  │ ├── cmd_summary.py # `gapit summary` CLI (registered from cli.py)
106
111
  │ ├── cmd_typing.py # `gapit typing` CLI (registered from cli.py)
@@ -156,7 +161,7 @@ This is what distinguishes gapit from abricate. Treat it as a public API.
156
161
  - **Formats**: `--format tsv|csv|json|md` (default `tsv` for abricate compatibility).
157
162
  - **JSON**: top-level `"schema": "gapit.report/1"`; schema introspectable via
158
163
  `gapit schema report | reads | reads2 | summary | list | error | version` (plus
159
- `cluster | features | typing | typing_result`). Keys are snake_case,
164
+ `cluster | features | typing | typing_result | floors`). Keys are snake_case,
160
165
  units explicit (`identity_pct`, `coverage_pct`). Semver the schema; never rename or
161
166
  retype a field in a minor bump.
162
167
  - **Markdown**: YAML frontmatter (tool version, db, params, ISO-8601 UTC timestamp) + tables a
@@ -173,12 +178,12 @@ This is what distinguishes gapit from abricate. Treat it as a public API.
173
178
  database fetch from the provider catalog (every provider downloads from upstream at fetch
174
179
  time — nothing catalog-side is bundled inside the wheel beyond the sanctioned exceptions,
175
180
  a license-compliance requirement: CARD/VFDB terms are non-commercial and Kaptive is GPL,
176
- so none of those may ride an MIT distribution; the sanctioned exceptions are the five
181
+ so none of those may ride an MIT distribution; the sanctioned exceptions are the six
177
182
  content-provenance-audited bundles under `src/gapit/data/dbs/` — the public-domain
178
- `ecoli_dec` panel plus four permissively licensed provider snapshots (`ncbi` public
179
- domain, `resfinder` Apache-2.0, `ecoh` BSD-3-Clause, `upec_expec_vf` MIT; GPL/NC content
180
- is never bundled) — materialized into the datadir on first use via `bundled.py`, with
181
- `db fetch <name>` still the fresh-upstream refresh path),
183
+ `ecoli_dec` and `lm_doumith` panels plus four permissively licensed provider snapshots
184
+ (`ncbi` public domain, `resfinder` Apache-2.0, `ecoh` BSD-3-Clause, `upec_expec_vf`
185
+ MIT; GPL/NC content is never bundled) — materialized into the datadir on first use via
186
+ `bundled.py`, with `db fetch <name>` still the fresh-upstream refresh path),
182
187
  database listing,
183
188
  records.jsonl gene search, staleness
184
189
  report, custom FASTA→native-db build, GBK/GFF→cluster-db build (`--typing` installs a
@@ -200,7 +205,9 @@ This is what distinguishes gapit from abricate. Treat it as a public API.
200
205
  committed files deliberately and review diffs like code.
201
206
  - **Parity harness**: `pixi run -e parity parity` (and `summary-parity`) runs real abricate
202
207
  (conda) and gapit over a small genome corpus and diffs the gene calls byte-for-byte (file,
203
- gene, %identity, %coverage). Parity on the corpus is the release gate for v1.0.
208
+ gene, %identity, %coverage). **From v0.5.0 this is a regression reference for the frozen
209
+ baseline surface, not a release gate for new work** — new features need not check abricate
210
+ and may diverge deliberately.
204
211
  - Full suite + CI matrix 3.11/3.13/3.14; parity byte-diff is opt-in via the `parity` pixi env.
205
212
  Offline tests stay fast.
206
213
 
@@ -216,13 +223,15 @@ This is what distinguishes gapit from abricate. Treat it as a public API.
216
223
  query contigs against one db → 15-field
217
224
  tabular hits → filter by identity / coverage thresholds → **dedup hits sharing identical
218
225
  `(contig, qstart, qend)`** (first/best BLAST row wins) → one TSV row per surviving hit.
219
- abricate does **not** merge overlapping intervals — do not "improve" this on the default path (the
220
- opt-in `--merge-fragments` cross-contig extension is the one sanctioned exception:
221
- `fragments.py`).
226
+ The default path does **not** merge overlapping intervals (frozen baseline behavior;
227
+ the opt-in `--merge-fragments` cross-contic extension in `fragments.py` is the sanctioned
228
+ exception).
222
229
  - Key computed fields: `%COVERAGE = 100*(length-gaps)/slen` (filtered unrounded, displayed
223
230
  `%.2f`), `%IDENTITY` (BLAST pident, never post-filtered), `COVERAGE_MAP` (15-char minimap),
224
- `GAPS`. Exact formulas, the dedup rule, and the minimap arithmetic live in `SPEC.md` — when
225
- abricate and intuition disagree, **abricate wins** (parity is a feature).
231
+ `GAPS`. Exact formulas, the dedup rule, and the minimap arithmetic live in `SPEC.md` — they
232
+ are **gapit's frozen contract** for the baseline surface: do not change them silently. New
233
+ surfaces (reads, cluster, typing) follow their own documented contracts and may diverge from
234
+ abricate by design.
226
235
 
227
236
  ## 8. Git & workflow
228
237
 
@@ -5,6 +5,164 @@ All notable changes to gapit are documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this
6
6
  project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.5.2] - 2026-10-03
9
+
10
+ ### Added
11
+
12
+ - **Per-gene identity floors for reads-mode presence (`gapit.floors/1`) — the db-driven
13
+ fix for the 26ECO0084 `pic` SPATE false positive.** A gene database may carry an
14
+ optional `floors.json` sidecar declaring a minimum alignment identity (%) per gene:
15
+ in reads mode, alignments to a floored gene below its floor are dropped BEFORE
16
+ aggregation, so breadth is recomputed from the surviving rows (a ~86.6%-identity,
17
+ 97.59%-breadth SPATE homolog collapses below the presence threshold instead of
18
+ over-calling `pic`, matching the blastn contig verdict). **Strictly opt-in via
19
+ DATABASE metadata, not a CLI change**: a database without the sidecar screens
20
+ byte-identically to before, existing databases need nothing, and the blastn contig
21
+ path never reads floors (`--minid` already gates it). Floors compose conjunctively
22
+ with `gapit.reads/2` `--min-identity` (a row must clear both); `gapit.reads/1`
23
+ output shape is untouched (presence/breadth changes only for floored genes). New
24
+ module `gapit.gene_floors` (model registered as `gapit schema floors`), `gapit db
25
+ build NAME.fa --floors FILE` (gene builds only; cluster inputs reject it) installs a
26
+ validated copy — every listed gene must exist in the FASTA (`FLOORS_UNKNOWN_GENE`),
27
+ values in [0, 100] and structure per the schema (`FLOORS_MALFORMED`); dropping the
28
+ file into an existing db directory works too. The bundled `ecoli_dec` now ships
29
+ `{"genes": {"pic": 90.0}}` (true `pic` ≥95%; `astA` deliberately unfloored — true
30
+ alleles at 90.4–91% leave no margin), materialized with the bundle; MCP `screen_reads`
31
+ inherits the gate through the shared use-case.
32
+
33
+ - **Bundled `lm_doumith`: Listeria monocytogenes serogrouping (Doumith 2004) — the sixth
34
+ bundled database.** Five markers extracted from public-domain INSDC records (`prs`,
35
+ `lmo0737`, `lmo1118`, `ORF2819`, `ORF2110`; strand-corrected, `lmo0737` verified against
36
+ EGD-e) behind the `gapit.typing/2` scheme `doumith_serogroup` (95/95 floors, `prs`
37
+ control gene, cutoff 1.0 / margin 0.0). Rules follow Doumith's multiplex-PCR table
38
+ (IIa = 1/2a·3a, IIc = 1/2c·3c, IIb = 1/2b·3b·7, IVb = 4b·4d·4e) extended with Huang
39
+ 2011's 4b variant (`IVb-v`, declared before `IVb` so an lmo0737-carrying 4b profile
40
+ resolves to the variant); fallback `untypeable (4a/4c, atypical profile, or non-Lm
41
+ Listeria)`. Materializes on first screen like every bundle (zero network);
42
+ `tests/test_lm_doumith.py` pins the synthetic marker-subset matrix, the control gate,
43
+ the two-stage golden, and the bundled integration — the bundled roster grows to six
44
+ (discovery, red-flag scan, `db list`, and `setupdb` pins updated). Uppercase gene ids
45
+ (`ORF2819`/`ORF2110`) now ride a shipped database, locking that build/screen/typing
46
+ carry them verbatim.
47
+
48
+ ## [0.5.1] - 2026-10-03
49
+
50
+ ### Added
51
+
52
+ - **Illumina FASTQ wildcard support: `gapit screen -d ecoli_dec *.gz` screens a shell glob
53
+ of reads without `--r1`/`--r2`** (rightsholder batch workflow). When every positional file
54
+ is FASTQ — a `.fastq`/`.fq` (± `.gz`) extension, or content sniffed as FASTQ when the
55
+ extension is ambiguous (via the existing `detect_read_kind`; known contig extensions and
56
+ garbage content keep today's contig pipeline untouched) — the command enters reads mode
57
+ and auto-pairs samples from filenames (`gapit.readpairs`, new): mate markers `_R1_001`/
58
+ `_R2_001` (bcl2fastq; an `_L00x` lane tag stays in the sample key), `_R1`/`_R2`, `_1`/`_2`,
59
+ `.1`/`.2`, all case-insensitive, longest suffix first, extensions `.fastq`/`.fq` ×
60
+ `.gz`/`.bz2` stripped before matching. The document carries one `files[]` entry per sample
61
+ (`reads[]` holds the sample key; per-gene metrics union over the sample's lanes; samples
62
+ sorted lexicographically). A file whose mate is missing, or with no detectable marker,
63
+ screens single-end with a quiet-respecting stderr `WARNING: no mate found for X —
64
+ screening single-end` — a warning, never an error. Duplicate identical basenames merge as
65
+ extra lanes of one sample. Mixing FASTA and FASTQ positionals is a usage error naming the
66
+ reads files; the reads-mode guards fire as on `--r1`/`--r2` (`--minid`/`--mincov`,
67
+ `--merge-fragments`, ... rejected), while `--min-identity`/`--min-mapq` now work on this
68
+ path (gapit.reads/2). `--read-type` keeps
69
+ the content-based preset resolution (`sr` for FASTQ). **`--jobs` is legal on this path
70
+ only** (the `--r1`/`--r2` single-sample invocation keeps the frozen rejection): samples
71
+ screen concurrently through a ThreadPoolExecutor whose positional yields keep output in
72
+ sample order byte-identical to `-j 1` (a failing sample raises at its position; the
73
+ `--jobs × --threads` oversubscription stderr note and the `--jobs >= 1` validation mirror
74
+ the contig path). **Output defaults to streaming tsv on this path**: the `#SAMPLE` header
75
+ leads, then each sample's gene rows land the moment its screening completes (`--format
76
+ csv` is the comma spelling), so a terminal shows per-sample results as they arrive; json
77
+ stays the opt-in single document written at the end (`--format json`; since the same
78
+ cycle's format-unification it is the opt-in on the `--r1`/`--r2` path too — see Changed).
79
+ md emits
80
+ a static frontmatter first (no run totals on this path — totals live in the JSON
81
+ document; the `--r1`/`--r2` render keeps its `files:`/`genes_found:` frontmatter
82
+ unchanged) then one `## <sample>` section per completed sample, head-of-line in sample
83
+ order under `--jobs`; `--output` writes the streamed chunks incrementally, so a
84
+ mid-batch failure persists samples 1..k-1 (tsv/md) and nothing at all (json). The
85
+ single-sample `--r1`/`--r2` path, the blastn contig path, and
86
+ the explicit `--aligner` routings are unchanged.
87
+ - **`gapit typing` closes every TSV/MD row with a `GENES` column and `gapit.typing_result/1`
88
+ gains the additive per-file `genes` list** (schema stays `/1`; additive field, the
89
+ 0.5.0 shape unchanged otherwise): the FILE's present gene names — the folded best hits the
90
+ designation ran on — sorted alphabetically and `;`-joined, repeated on each of the FILE's
91
+ scheme rows so each call is auditable against the hits that drove it. JSON carries the same
92
+ list as `files[].genes`.
93
+ - **`gapit summary` reads its report table from stdin** — the pipe twin of `gapit typing`:
94
+ `gapit screen -d ecoli_dec *.fna --quiet | gapit summary` summarizes the batched screen
95
+ output straight off the pipe (a piped table is one input, so dutch mode applies — one row
96
+ per FILE value, byte-identical to summarizing the `-o`-written table). Stdin is read
97
+ whenever stdin is not a terminal; a bare invocation at a terminal keeps printing help;
98
+ `gapit summary -` is the explicit stdin marker (reads until EOF even under a terminal);
99
+ mixing `-` with file arguments is a usage error; non-UTF-8 stdin is the `SUMMARY_MALFORMED`
100
+ envelope naming `-`. The flag-but-no-file invocation (`summary --quiet` with a pipe) now
101
+ reads stdin instead of the former USAGE_ERROR.
102
+
103
+ - **`--db` now also answers to the word-style alias `-db`** (on `gapit screen` and
104
+ `gapit db search`): `-db ecoli_dec` parses exactly like `--db ecoli_dec`, matching the
105
+ tar-style single-dash habit that previously misparsed as `-d b` + a positional. The
106
+ space-separated form is the supported one — click binds an attached `-dbecoli_dec` to
107
+ `-d` with value `becoli_dec` (the original failure), which the new guard below catches.
108
+
109
+ ### Fixed
110
+
111
+ - **A positional argument that names a known database but is missing on disk now fails with
112
+ a targeted usage error (exit 2)** instead of the generic INPUT_NOT_FOUND (exit 5) plus a
113
+ starved downstream pipe: `gapit screen -d b ecoli_dec X.fna` (the stripped `-db` misparse
114
+ shape) reports `input file not found: 'ecoli_dec' — it is a database NAME; screen takes
115
+ databases via --db/-d/-db (e.g. --db ecoli_dec), positional arguments are genome files`.
116
+ Database names are matched against the provider catalog, bundled wheel content, and
117
+ installed datadir databases; ordinary missing files keep today's INPUT_NOT_FOUND.
118
+
119
+ ### Changed
120
+
121
+ - **Breaking: `gapit screen` reads mode now defaults to streaming tsv on EVERY path** —
122
+ `--r1`/`--r2` and `--aligner minimap2` join the positional wildcard (and the blastn contig
123
+ path) with tsv as the human default; json/md are the explicit agent opt-ins. tsv is the
124
+ human default on every surface; json (`gapit.reads/1`/`2`) and md are the opt-ins for
125
+ agents. The default output is the same streaming `#SAMPLE` table the wildcard emits (one
126
+ chunk for the single sample; preamble + chunk compose exactly the buffered render);
127
+ `--format csv` is the comma spelling, `--format json`/`--format md` unchanged. The former
128
+ reads json default shipped ≤0.5.0 — invocations that relied on it must now pass
129
+ `--format json` (the tsv/csv reads-mode usage rejection is gone with it). The MCP
130
+ `screen`/`screen_reads` tools are unchanged: they pass `format` explicitly and still
131
+ return json by default (the agents' surface).
132
+
133
+ ### Added
134
+
135
+ - `gapit summary --coverage` / `-c`: cells show %COVERAGE values (`;`-joined), reproducing the
136
+ classic abricate `--summary` cell shape byte-for-byte (the parity harness now runs in this
137
+ mode). `-ic` combines both metrics: each hit renders `identity/coverage`. `gapit typing` TSV/MD: the `GENES` column moved to follow `PHENOTYPE`
138
+ (was last; additive JSON `files[].genes` unchanged).
139
+
140
+ ### Changed
141
+
142
+ - **Breaking**: `gapit summary` default cells are now the presence call (`+` / `-`) instead of
143
+ %COVERAGE values — pass `--coverage` to restore the previous cell shape.
144
+
145
+ ### Changed
146
+
147
+ - **Project stance**: from v0.5.0 onward gapit pursues its own contract — abricate parity is no
148
+ longer a design goal. The contig TSV stays a frozen historical baseline (kept for existing
149
+ pipelines); the parity harness is a regression reference, not a release gate. New surfaces may
150
+ diverge from abricate by design. (AGENTS.md updated accordingly.)
151
+ - Reads tables: the default lists present genes only (`--all-genes` / `-A` adds absent
152
+ calls) and the last column is `PRODUCT` (the `RESISTANCE` column is dropped from reads
153
+ tables; the contig table keeps it).
154
+
155
+ ### Fixed
156
+
157
+ - **Reads-mode breadth accuracy (26ECO0071 astA)**: minimap2 now always runs with `--cs`
158
+ and the `sr` preset carries `-k11 -w6 -B2`. Two stacked defects silently dropped
159
+ diverged-allele genes from FASTQ screening (the assembly/BLAST path found astA, reads did
160
+ not): (1) the stock `sr` seed (k=21) finds no exact run on a ~90%-identity 117 bp gene —
161
+ zero alignments regardless of scoring; (2) minimap2's no-CIGAR mode emits clipped
162
+ alignment coordinates (57% vs 100% breadth on the same data). Presence calls and typing
163
+ inputs derived from reads screening change accordingly; the reads goldens were regenerated
164
+ deliberately.
165
+
8
166
  ## [0.5.0] - 2026-10-02
9
167
 
10
168
  ### Breaking
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: gapit
3
- Version: 0.5.0
3
+ Version: 0.5.2
4
4
  Summary: Mass screening of contigs and reads for known genes — agent-first Python reimplementation of abricate
5
5
  Project-URL: Homepage, https://github.com/indexofire/gapit
6
6
  Project-URL: Documentation, https://indexofire.github.io/gapit/
@@ -91,7 +91,7 @@ gapit screen --r1 ont_reads.fastq.gz --db ncbi --read-type map-ont --format json
91
91
  # Summarize report tables into a gene presence/absence matrix
92
92
  gapit summary *.tsv
93
93
 
94
- # Databases: five ship in-wheel and work instantly; the rest download from upstream on fetch
94
+ # Databases: six ship in-wheel and work instantly; the rest download from upstream on fetch
95
95
  gapit db fetch all # default set (card, vfdb)
96
96
  gapit db fetch ncbi
97
97
  gapit db list
@@ -111,8 +111,9 @@ presence defaults to 90% alignment breadth (`--min-breadth 90`).
111
111
  A database is a directory under the datadir, resolved from `$GAPIT_DATADIR`, then
112
112
  `~/.local/share/gapit/db` (override per call with `--datadir`). Twelve databases are built
113
113
  into the catalog; all of them download from upstream and build on `gapit db fetch` — with
114
- five content-provenance-audited exceptions that ship inside the package (`ecoli_dec` plus
115
- the `ncbi`, `resfinder`, `ecoh`, `upec_expec_vf` snapshots: public domain / Apache-2.0 /
114
+ six content-provenance-audited exceptions that ship inside the package (`ecoli_dec` and
115
+ `lm_doumith` plus the `ncbi`, `resfinder`, `ecoh`, `upec_expec_vf` snapshots: public
116
+ domain / Apache-2.0 /
116
117
  BSD-3-Clause / MIT), materialized into the datadir on first use with zero network. Several
117
118
  upstream licenses (CARD's McMaster terms, VFDB's CC BY-NC, Kaptive's GPL-3.0) forbid
118
119
  redistribution inside an MIT-licensed distribution, so everything else is fetch-on-demand
@@ -204,6 +205,6 @@ guide, `CHANGELOG.md` the change history.
204
205
 
205
206
  gapit is MIT-licensed. It is a behavioral reimplementation of abricate (GPL-2.0) and
206
207
  copies no Perl code; abricate itself remains GPL-2.0. The only database content inside
207
- the package is the five audited, permissively licensed bundles under `src/gapit/data/dbs/`
208
+ the package is the six audited, permissively licensed bundles under `src/gapit/data/dbs/`
208
209
  (public domain / Apache-2.0 / BSD-3-Clause / MIT); every other provider downloads from
209
210
  upstream at fetch time, under its own license (SPEC.md §9).
@@ -61,7 +61,7 @@ gapit screen --r1 ont_reads.fastq.gz --db ncbi --read-type map-ont --format json
61
61
  # Summarize report tables into a gene presence/absence matrix
62
62
  gapit summary *.tsv
63
63
 
64
- # Databases: five ship in-wheel and work instantly; the rest download from upstream on fetch
64
+ # Databases: six ship in-wheel and work instantly; the rest download from upstream on fetch
65
65
  gapit db fetch all # default set (card, vfdb)
66
66
  gapit db fetch ncbi
67
67
  gapit db list
@@ -81,8 +81,9 @@ presence defaults to 90% alignment breadth (`--min-breadth 90`).
81
81
  A database is a directory under the datadir, resolved from `$GAPIT_DATADIR`, then
82
82
  `~/.local/share/gapit/db` (override per call with `--datadir`). Twelve databases are built
83
83
  into the catalog; all of them download from upstream and build on `gapit db fetch` — with
84
- five content-provenance-audited exceptions that ship inside the package (`ecoli_dec` plus
85
- the `ncbi`, `resfinder`, `ecoh`, `upec_expec_vf` snapshots: public domain / Apache-2.0 /
84
+ six content-provenance-audited exceptions that ship inside the package (`ecoli_dec` and
85
+ `lm_doumith` plus the `ncbi`, `resfinder`, `ecoh`, `upec_expec_vf` snapshots: public
86
+ domain / Apache-2.0 /
86
87
  BSD-3-Clause / MIT), materialized into the datadir on first use with zero network. Several
87
88
  upstream licenses (CARD's McMaster terms, VFDB's CC BY-NC, Kaptive's GPL-3.0) forbid
88
89
  redistribution inside an MIT-licensed distribution, so everything else is fetch-on-demand
@@ -174,6 +175,6 @@ guide, `CHANGELOG.md` the change history.
174
175
 
175
176
  gapit is MIT-licensed. It is a behavioral reimplementation of abricate (GPL-2.0) and
176
177
  copies no Perl code; abricate itself remains GPL-2.0. The only database content inside
177
- the package is the five audited, permissively licensed bundles under `src/gapit/data/dbs/`
178
+ the package is the six audited, permissively licensed bundles under `src/gapit/data/dbs/`
178
179
  (public domain / Apache-2.0 / BSD-3-Clause / MIT); every other provider downloads from
179
180
  upstream at fetch time, under its own license (SPEC.md §9).
@@ -265,8 +265,12 @@ preset resolution added 2026-09-19):
265
265
  `reads_mapped` = distinct query names with ≥1 primary alignment on the gene.
266
266
  - **Presence call**: `present = breadth_pct >= min_breadth`, `--min-breadth` default **90.0**
267
267
  (srst2-style). `--minid`/`--mincov` do NOT apply to reads mode.
268
- - **Output**: `--format json` (default in reads mode) emits `gapit.reads/1`; `--format md` the
269
- Markdown form; `--format tsv|csv` in reads mode is a usage error (exit 2). Genes with zero
268
+ - **Output**: the default (no `--format`) is the streaming **tsv** table (tsv is the human
269
+ default on every gapit surface; json/md are the agent opt-ins — breaking vs the ≤0.5.0
270
+ reads default, changed in the unreleased cycle; §10 describes gapit's own reads extension,
271
+ so this wording is normative for gapit only, not for the abricate parity path).
272
+ `--format json` emits `gapit.reads/1`; `--format md` the Markdown form; `--format csv` is
273
+ the comma spelling of the tsv table. Genes with zero
270
274
  mapped reads are omitted; entries sorted by `breadth_pct` descending, then gene name.
271
275
  `gapit.report/1` (contig mode) is unchanged and frozen. `gapit schema reads` introspects the
272
276
  new document.
@@ -13,7 +13,7 @@ Version, as one JSON line:
13
13
 
14
14
  ```console
15
15
  $ gapit --version --json
16
- {"schema":"gapit.version/1","name":"gapit","version":"0.5.0"}
16
+ {"schema":"gapit.version/1","name":"gapit","version":"0.5.2"}
17
17
  ```
18
18
 
19
19
  Output schemas. Ten documents are introspectable: `report`, `typing_result`, `reads`,
@@ -12,7 +12,7 @@ gapit 生来就是被程序驱动的。每个输出都以机器可读为设计
12
12
 
13
13
  ```console
14
14
  $ gapit --version --json
15
- {"schema":"gapit.version/1","name":"gapit","version":"0.5.0"}
15
+ {"schema":"gapit.version/1","name":"gapit","version":"0.5.2"}
16
16
  ```
17
17
 
18
18
  输出 schema。十个文档可自省:`report`、`typing_result`、`reads`、`reads2`、`cluster`、
@@ -44,6 +44,7 @@ vfdb USTC (VFDB) available nucl VFDB virulence factors (set A, nucleotide)
44
44
  victors University of Chicago available nucl Victors virulence factors
45
45
  ecoh Holt lab (srst2) bundled nucl E. coli O and H antigens (srst2 EcOH)
46
46
  ecoli_dec gapit-curated (public-domain sources) bundled nucl Diarrheagenic E. coli marker panel (GB 4789.6 + risk-monitoring designation)
47
+ lm_doumith gapit-curated (public-domain INSDC sources) bundled nucl Listeria monocytogenes serogrouping (Doumith 2004)
47
48
  ncbi NCBI bundled nucl NCBI AMRFinderPlus (reference finder) curated AMR
48
49
  resfinder DTU CGE bundled nucl CGE ResFinder acquired resistance genes
49
50
  upec_expec_vf FordeGenomics bundled nucl UPEC/ExPEC virulence genes (FordeGenomics)
@@ -51,7 +52,7 @@ upec_expec_vf FordeGenomics bundled nucl UPEC/ExPEC virulence genes (FordeGenomi
51
52
 
52
53
  NAME is the database name you pass to `--db`; PROVIDER names the upstream maintainer
53
54
  organisation. STATUS reads `installed (N)` when `<datadir>/<name>/gapit-manifest.json`
54
- exists, with N the record count, otherwise `available`. The last five rows are the
55
+ exists, with N the record count, otherwise `available`. The last six rows are the
55
56
  wheel-shipped [bundled](#bundled-databases-install-time-ready) databases, alphabetical:
56
57
  `bundled` before materialization, `installed (N)` after. Four of them (`ecoh`, `ncbi`,
57
58
  `resfinder`, `upec_expec_vf`) are also registry providers — such names render exactly
@@ -121,7 +122,7 @@ surface.) See [outputs.md](./outputs.md).
121
122
 
122
123
  Most databases download from upstream at `db fetch` time because their licenses forbid
123
124
  redistribution (see [Providers](#providers)). A small set of **bundled** databases ships
124
- inside the gapit wheel instead — five databases whose content provenance was audited
125
+ inside the gapit wheel instead — six databases whose content provenance was audited
125
126
  record-by-record (public-domain sources, or Apache-2.0 / BSD-3-Clause / MIT panels;
126
127
  GPL and non-commercial content never rides the wheel). Nothing to download, nothing to
127
128
  accept: a bundled database works out of the box.
@@ -130,6 +131,7 @@ accept: a bundled database works out of the box.
130
131
  |---|---|---|---|
131
132
  | `ecoh` | E. coli O and H antigens (597 records, srst2 EcOH) | 2026-10-02 | — |
132
133
  | `ecoli_dec` | Diarrheagenic E. coli marker panel (17 records, GB 4789.6 + risk-monitoring designation) | 2026-10-02 | `gapit.typing/2` (schemes `gb4789_6`, `risk_monitoring`) |
134
+ | `lm_doumith` | Listeria monocytogenes serogrouping (5 records, Doumith 2004 markers) | 2026-10-03 | `gapit.typing/2` (scheme `doumith_serogroup`) |
133
135
  | `ncbi` | NCBI AMRFinderPlus curated AMR (8373 records) | 2026-10-02 | — |
134
136
  | `resfinder` | CGE ResFinder acquired resistance genes (3206 records) | 2026-10-02 | — |
135
137
  | `upec_expec_vf` | UPEC/ExPEC virulence genes (77 records, FordeGenomics) | 2026-10-02 | — |
@@ -137,13 +139,15 @@ accept: a bundled database works out of the box.
137
139
  **License provenance.** Every `ecoli_dec` record was re-sourced from primary
138
140
  public-domain submissions (NCBI RefSeq/GenBank/DDBJ accessions, same alleles as the
139
141
  rightsholder panel); two VFDB-derived records found in the original panel were removed
140
- and replaced during the 2026-10 audit. The four provider snapshots (`ecoh`, `ncbi`,
141
- `resfinder`, `upec_expec_vf`) passed the 2026-10 content-level audit across **all**
142
- records: NCBI AMRFinderPlus content is public domain (US government work), the CGE
143
- ResFinder database is Apache-2.0, srst2's EcOH is BSD-3-Clause, and FordeGenomics'
144
- UPEC-ExPEC panel is MIT — all four permits redistribution inside the MIT-licensed wheel.
145
- A regression test pins that no `VF*` / `VFDB` / `ARO:` tags appear in any of the five
146
- bundles' headers.
142
+ and replaced during the 2026-10 audit. The `lm_doumith` panel was extracted the same
143
+ way from public-domain INSDC records (accessions in each header; reverse-complement
144
+ markers strand-corrected, `lmo0737` verified 100% against EGD-e). The four provider
145
+ snapshots (`ecoh`, `ncbi`, `resfinder`, `upec_expec_vf`) passed the 2026-10
146
+ content-level audit across **all** records: NCBI AMRFinderPlus content is public
147
+ domain (US government work), the CGE ResFinder database is Apache-2.0, srst2's EcOH
148
+ is BSD-3-Clause, and FordeGenomics' UPEC-ExPEC panel is MIT — all four permits
149
+ redistribution inside the MIT-licensed wheel. A regression test pins that no `VF*` /
150
+ `VFDB` / `ARO:` tags appear in any of the six bundles' headers.
147
151
 
148
152
  **Snapshots are point-in-time.** Each snapshot's `sequences` file is byte-for-byte what
149
153
  `gapit db fetch <name>` produces from upstream on the snapshot date (a regression test
@@ -167,6 +171,36 @@ manifest exists. `db list` shows the database as `bundled` before that and
167
171
  `installed (17)` after — on all four listing surfaces (TSV, rich table, `--json`, MCP
168
172
  `db_list`).
169
173
 
174
+ ### Listeria serogrouping (`lm_doumith`)
175
+
176
+ The typed bundle behind Listeria monocytogenes serogroup prediction: five markers —
177
+ `prs`, `lmo0737`, `lmo1118`, `ORF2819`, `ORF2110` — screened with 95/95 identity and
178
+ coverage floors and folded by the `doumith_serogroup` scheme into Doumith's multiplex-PCR
179
+ groups (Doumith et al. 2004, J Clin Microbiol 42:3819), extended with the Huang 2011
180
+ 4b variant: `prs` gates the scheme as a genus-level control gene, `IIa` (1/2a or 3a),
181
+ `IIc` (1/2c or 3c), `IIb` (1/2b, 3b or 7), `IVb` (4b, 4d or 4e), and `IVb-v` (the
182
+ lmo0737-carrying 4b variant) — the same in-silico semantics as tools like LisSero.
183
+ Designation runs through the two-stage pipeline: `gapit screen -o table.tsv --db
184
+ lm_doumith`, then `gapit typing table.tsv`.
185
+
186
+ Known limitations, carried on the calls as notes where relevant:
187
+
188
+ - **4b/4d/4e are unresolvable at gene level** — the three serovars share every published
189
+ molecular marker; resolve by cgMLST or antisera.
190
+ - **IVb-v is an emergent concern** — lmo0737 in an otherwise-4b profile (Huang 2011
191
+ "unusual 4b"; ST382/ST554 clones) is declared before IVb so the variant wins.
192
+ - **EGD-e types as IIc** — the 1/2a reference genome carries lmo1118 and lands in IIc;
193
+ documented in Doumith 2004, not a tool artifact.
194
+ - **Horizontal gene transfer cuts both ways** — the lineage-II lmo0737 cassette moves
195
+ between lineages, and rare HGT of the ORF markers can produce false IIb-looking
196
+ profiles; treat single-marker IIb calls in epidemiologically unlikely contexts with
197
+ care.
198
+ - **`prs` is genus-level, not Lm-specific** — other Listeria species carry it; a prs+
199
+ isolate with no serogroup markers falls back rather than being called non-Listeria.
200
+
201
+ The fallback call — `untypeable (4a/4c, atypical profile, or non-Lm Listeria)` — is the
202
+ honest answer for everything the five markers cannot resolve.
203
+
170
204
  ## Checking database freshness
171
205
 
172
206
  `gapit db outdated` reports every installed database's age against the staleness
@@ -263,7 +297,7 @@ unknown `--db NAME` is a usage error (exit 2) listing what is installed.
263
297
  ## Providers
264
298
 
265
299
  Nineteen providers ship with gapit. Every one of them — `card` and `vfdb` included —
266
- downloads from its upstream source at fetch time: with the exception of the five
300
+ downloads from its upstream source at fetch time: with the exception of the six
267
301
  audited, permissively licensed bundles above, nothing is bundled inside the package,
268
302
  because several upstream licenses (CARD's McMaster terms, VFDB's CC BY-NC, Kaptive's
269
303
  GPL-3.0) forbid redistribution inside an MIT-licensed distribution. The seven kaptive
@@ -410,6 +444,8 @@ $ gapit db install card.json \
410
444
  sequences generated FASTA projection (gapit/v1 tagged headers)
411
445
  sequences.n*|p* BLAST index built from sequences
412
446
  gapit-manifest.json provenance sidecar, written last
447
+ typing.json optional gapit.typing/1 or /2 scoring spec (typed dbs)
448
+ floors.json optional gapit.floors/1 per-gene identity floors (reads mode)
413
449
  ```
414
450
 
415
451
  ### records.jsonl
@@ -452,7 +488,7 @@ versions. A real one, from the plasmidfinder database:
452
488
  "upstream_version": "",
453
489
  "tool": {
454
490
  "name": "gapit",
455
- "version": "0.5.0"
491
+ "version": "0.5.2"
456
492
  },
457
493
  "makeblastdb_version": "blastn: 2.17.0+",
458
494
  "minimap2_version": "2.31-r1302"
@@ -479,6 +515,31 @@ versions. A real one, from the plasmidfinder database:
479
515
  `records.jsonl` and the manifest are file contracts. They never appear on stdout and are
480
516
  not registered with `gapit schema`.
481
517
 
518
+ ### floors.json — per-gene identity floors
519
+
520
+ An optional sidecar declaring a MINIMUM alignment identity (%) per gene for reads-mode
521
+ presence (schema `gapit.floors/1`, introspect with `gapit schema floors`; see
522
+ [reads.md](./reads.md#per-gene-identity-floors-gapitfloors1-database-side) for the
523
+ screening semantics and the `pic` worked example):
524
+
525
+ ```json
526
+ {"schema": "gapit.floors/1", "default": null, "genes": {"pic": 90.0}}
527
+ ```
528
+
529
+ | Field | Type | Meaning |
530
+ |---|---|---|
531
+ | `schema` | string | Always `gapit.floors/1` |
532
+ | `default` | number or null | Floor for genes not listed in `genes` (`null` = no floor) |
533
+ | `genes` | object | `{gene: minimum identity %}`, values in [0, 100] |
534
+
535
+ The file's presence IS the flag — no manifest field, no CLI switch. A database without
536
+ the sidecar screens byte-identically to before (the floors are a db-driven opt-in, not a
537
+ CLI contract change), and the blastn contig path never reads them. Built-in via
538
+ `db build --floors` (next sections), or drop the file into an existing db directory; it
539
+ is validated at screening time too (malformed content fails with `FLOORS_MALFORMED`,
540
+ exit 4). The bundled `ecoli_dec` ships `{"genes": {"pic": 90.0}}` — the SPATE-homolog
541
+ false-positive fix.
542
+
482
543
  ## Header formats and compatibility
483
544
 
484
545
  gapit reads two header formats and detects them per record:
@@ -581,6 +642,27 @@ gene accession function
581
642
  syn_betalac SYN-0001 ampicillin;cephalosporin
582
643
  ```
583
644
 
645
+ ### Per-gene identity floors (`--floors`)
646
+
647
+ `--floors FILE` installs a `gapit.floors/1` document as the database's `floors.json`
648
+ sidecar — the per-gene minimum alignment identity for reads-mode presence (see
649
+ [reads.md](./reads.md#per-gene-identity-floors-gapitfloors1-database-side)). The
650
+ document is validated before any artifact is written: every gene in `genes` must exist
651
+ in the FASTA (`FLOORS_UNKNOWN_GENE`, exit 4 — a floor for a missing gene is silently
652
+ dead safety config), values must lie in [0, 100] and the structure parse
653
+ (`FLOORS_MALFORMED`, exit 4). The file is then copied in byte-identical; the file's
654
+ presence is the flag (no manifest field changes). Gene builds only — a GBK/GFF cluster
655
+ input rejects `--floors` as a usage error.
656
+
657
+ ```console
658
+ $ cat my_floors.json
659
+ {"schema": "gapit.floors/1", "default": null, "genes": {"syn_betalac": 95.0}}
660
+ $ gapit db build tinyamr my_genes.fa --datadir ./db --tsv my_meta.tsv --floors my_floors.json
661
+ {"db":"tinyamr","records":2,"dbtype":"nucl","destination":"/tmp/opencode/gapit-build-demo/db/tinyamr"}
662
+ $ cat ./db/tinyamr/floors.json
663
+ {"schema": "gapit.floors/1", "default": null, "genes": {"syn_betalac": 95.0}}
664
+ ```
665
+
584
666
  ### Rebuilding
585
667
 
586
668
  Like `db fetch`, an existing database is never overwritten silently: