gapit 0.3.1__tar.gz → 0.5.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.
- {gapit-0.3.1 → gapit-0.5.0}/AGENTS.md +58 -15
- gapit-0.5.0/CHANGELOG.md +473 -0
- {gapit-0.3.1 → gapit-0.5.0}/PKG-INFO +39 -19
- {gapit-0.3.1 → gapit-0.5.0}/PLAN.md +75 -0
- {gapit-0.3.1 → gapit-0.5.0}/README.md +36 -16
- {gapit-0.3.1 → gapit-0.5.0}/SPEC.md +22 -26
- {gapit-0.3.1 → gapit-0.5.0}/docs/agents.md +18 -11
- gapit-0.5.0/docs/agents.zh.md +205 -0
- gapit-0.5.0/docs/custom-db.zh.md +434 -0
- gapit-0.5.0/docs/databases.md +745 -0
- gapit-0.5.0/docs/databases.zh.md +701 -0
- {gapit-0.3.1 → gapit-0.5.0}/docs/faq.md +22 -8
- gapit-0.5.0/docs/faq.zh.md +111 -0
- {gapit-0.3.1 → gapit-0.5.0}/docs/index.md +12 -9
- gapit-0.5.0/docs/index.zh.md +48 -0
- {gapit-0.3.1 → gapit-0.5.0}/docs/installation.md +19 -14
- gapit-0.5.0/docs/installation.zh.md +107 -0
- {gapit-0.3.1 → gapit-0.5.0}/docs/mcp.md +12 -12
- gapit-0.5.0/docs/mcp.zh.md +294 -0
- {gapit-0.3.1 → gapit-0.5.0}/docs/outputs.md +188 -14
- gapit-0.5.0/docs/outputs.zh.md +565 -0
- {gapit-0.3.1 → gapit-0.5.0}/docs/quickstart.md +44 -8
- gapit-0.5.0/docs/quickstart.zh.md +177 -0
- {gapit-0.3.1 → gapit-0.5.0}/docs/reads.md +7 -7
- gapit-0.5.0/docs/reads.zh.md +573 -0
- gapit-0.5.0/docs/screen.md +377 -0
- gapit-0.5.0/docs/screen.zh.md +361 -0
- {gapit-0.3.1 → gapit-0.5.0}/docs/summary.md +2 -2
- gapit-0.5.0/docs/summary.zh.md +179 -0
- gapit-0.5.0/docs/typing.md +328 -0
- gapit-0.5.0/docs/typing.zh.md +308 -0
- gapit-0.5.0/mkdocs.yml +69 -0
- {gapit-0.3.1 → gapit-0.5.0}/pixi.lock +11 -2
- {gapit-0.3.1 → gapit-0.5.0}/pixi.toml +2 -1
- {gapit-0.3.1 → gapit-0.5.0}/pyproject.toml +9 -9
- gapit-0.5.0/recipe/meta.yaml +70 -0
- gapit-0.5.0/scripts/cluster_calibration.py +183 -0
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/__init__.py +1 -1
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/blast.py +14 -3
- gapit-0.5.0/src/gapit/bundled.py +148 -0
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/cli.py +19 -9
- gapit-0.5.0/src/gapit/cluster.py +251 -0
- gapit-0.5.0/src/gapit/cluster_math.py +125 -0
- gapit-0.5.0/src/gapit/clusterbuild.py +200 -0
- gapit-0.5.0/src/gapit/cmd_db.py +124 -0
- gapit-0.5.0/src/gapit/cmd_db_build.py +111 -0
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/cmd_db_install.py +6 -6
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/cmd_db_outdated.py +11 -9
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/cmd_db_search.py +10 -6
- gapit-0.5.0/src/gapit/cmd_screen.py +279 -0
- gapit-0.5.0/src/gapit/cmd_screen_reads_args.py +38 -0
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/cmd_summary.py +8 -6
- gapit-0.5.0/src/gapit/cmd_typing.py +107 -0
- gapit-0.5.0/src/gapit/data/dbs/ecoh/bundled.json +7 -0
- gapit-0.5.0/src/gapit/data/dbs/ecoh/sequences +13445 -0
- gapit-0.5.0/src/gapit/data/dbs/ecoli_dec/bundled.json +7 -0
- gapit-0.5.0/src/gapit/data/dbs/ecoli_dec/sequences +352 -0
- gapit-0.5.0/src/gapit/data/dbs/ecoli_dec/typing.json +125 -0
- gapit-0.5.0/src/gapit/data/dbs/ncbi/bundled.json +7 -0
- gapit-0.5.0/src/gapit/data/dbs/ncbi/sequences +143433 -0
- gapit-0.5.0/src/gapit/data/dbs/resfinder/bundled.json +7 -0
- gapit-0.5.0/src/gapit/data/dbs/resfinder/sequences +54493 -0
- gapit-0.5.0/src/gapit/data/dbs/upec_expec_vf/bundled.json +7 -0
- gapit-0.5.0/src/gapit/data/dbs/upec_expec_vf/sequences +2648 -0
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/db.py +27 -3
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/db_build_ops.py +56 -8
- gapit-0.5.0/src/gapit/db_ops.py +286 -0
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/db_query_ops.py +4 -28
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/dbbuild.py +15 -5
- gapit-0.5.0/src/gapit/dispatch.py +72 -0
- gapit-0.5.0/src/gapit/engines.py +31 -0
- gapit-0.5.0/src/gapit/formats/cluster.py +236 -0
- gapit-0.5.0/src/gapit/formats/cluster_md.py +164 -0
- gapit-0.5.0/src/gapit/formats/json.py +158 -0
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/formats/md.py +60 -36
- gapit-0.3.1/src/gapit/formats/json.py → gapit-0.5.0/src/gapit/formats/reads_json.py +8 -111
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/formats/schemas.py +10 -6
- gapit-0.5.0/src/gapit/formats/tsv.py +67 -0
- gapit-0.5.0/src/gapit/formats/typing_result.py +146 -0
- gapit-0.5.0/src/gapit/fragments.py +131 -0
- gapit-0.5.0/src/gapit/gbfeatures.py +308 -0
- gapit-0.5.0/src/gapit/gffparse.py +204 -0
- gapit-0.5.0/src/gapit/hits.py +155 -0
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/mcp_schemas.py +25 -11
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/mcp_tools.py +22 -5
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/minimap2_run.py +8 -7
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/paf.py +16 -3
- gapit-0.5.0/src/gapit/providers/__init__.py +59 -0
- gapit-0.5.0/src/gapit/providers/ab_k.py +38 -0
- gapit-0.5.0/src/gapit/providers/ab_o.py +39 -0
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/providers/argannot.py +1 -1
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/providers/bacmet2.py +1 -1
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/providers/card.py +6 -1
- gapit-0.5.0/src/gapit/providers/cluster_common.py +82 -0
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/providers/common.py +19 -55
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/providers/ecoh.py +1 -1
- gapit-0.5.0/src/gapit/providers/ecoli_kps.py +39 -0
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/providers/ecoli_vf.py +6 -1
- gapit-0.5.0/src/gapit/providers/kosc_k.py +41 -0
- gapit-0.5.0/src/gapit/providers/kosc_o.py +41 -0
- gapit-0.5.0/src/gapit/providers/kpsc_k.py +40 -0
- gapit-0.5.0/src/gapit/providers/kpsc_o.py +40 -0
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/providers/megares.py +1 -1
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/providers/ncbi.py +1 -1
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/providers/plasmidfinder.py +1 -1
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/providers/resfinder.py +1 -1
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/providers/upec_expec_vf.py +1 -1
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/providers/vfdb.py +5 -1
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/providers/victors.py +1 -1
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/records.py +20 -3
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/report.py +3 -1
- gapit-0.5.0/src/gapit/screening.py +200 -0
- gapit-0.5.0/src/gapit/screening_cluster.py +166 -0
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/screening_reads.py +8 -3
- gapit-0.5.0/src/gapit/typing_decide.py +106 -0
- gapit-0.5.0/src/gapit/typing_engine.py +263 -0
- gapit-0.5.0/src/gapit/typing_gene.py +172 -0
- gapit-0.5.0/src/gapit/typing_input.py +234 -0
- gapit-0.5.0/src/gapit/typing_models.py +299 -0
- gapit-0.5.0/src/gapit/typing_ops.py +100 -0
- gapit-0.5.0/src/gapit/typing_results.py +110 -0
- gapit-0.5.0/src/gapit/typing_rules.py +179 -0
- gapit-0.5.0/tests/data/bundled_differential/resfinder/HEAD.zip +0 -0
- gapit-0.5.0/tests/data/bundled_differential/resfinder/README.md +15 -0
- gapit-0.5.0/tests/data/cluster/bakta_style.gbk +73 -0
- gapit-0.5.0/tests/data/cluster/clusters.gff3 +16 -0
- gapit-0.5.0/tests/data/cluster/clusters_gz.gff3.gz +0 -0
- gapit-0.5.0/tests/data/cluster/clusters_sidecar.fa +7 -0
- gapit-0.5.0/tests/data/cluster/clusters_sidecar.gff3 +8 -0
- gapit-0.5.0/tests/data/cluster/compound.gbk +19 -0
- gapit-0.5.0/tests/data/cluster/gz_input.gbk.gz +0 -0
- gapit-0.5.0/tests/data/cluster/kaptive_style.gbk +48 -0
- gapit-0.5.0/tests/data/cluster/nofasta.gff3 +8 -0
- gapit-0.5.0/tests/data/cluster/screening.gbk +82 -0
- gapit-0.5.0/tests/data/cluster/typing_invalid.json +9 -0
- gapit-0.5.0/tests/data/cluster/typing_screen.json +22 -0
- gapit-0.5.0/tests/data/cluster/typing_screen_cm.json +22 -0
- gapit-0.5.0/tests/data/cluster/typing_screen_v2.json +27 -0
- gapit-0.5.0/tests/data/cluster/typing_valid.json +31 -0
- gapit-0.5.0/tests/data/cluster/unnamed_cds.gbk +29 -0
- gapit-0.5.0/tests/data/fragments/fragdb/sequences +11 -0
- gapit-0.5.0/tests/data/fragments/split3040.fa +9 -0
- gapit-0.5.0/tests/data/fragments/split4060.fa +12 -0
- gapit-0.5.0/tests/data/fragments/split5050.fa +12 -0
- gapit-0.5.0/tests/data/typing/dec_s1_aggR_pic_uidA.fasta +100 -0
- gapit-0.5.0/tests/data/typing/dec_s2_pic_astA_uidA.fasta +90 -0
- gapit-0.5.0/tests/data/typing/dec_s3_stx2a_escV_aggR_uidA.fasta +85 -0
- gapit-0.5.0/tests/data/typing/exact.fa +39 -0
- gapit-0.5.0/tests/data/typing/listeria_1c.fa +29 -0
- gapit-0.5.0/tests/data/typing/listeria_4b.fa +32 -0
- gapit-0.5.0/tests/data/typing/listeria_nogate.fa +9 -0
- gapit-0.5.0/tests/data/typing/markers.fa +39 -0
- gapit-0.5.0/tests/data/typing/mutated.fa +39 -0
- gapit-0.5.0/tests/data/typing/negative.fa +30 -0
- gapit-0.5.0/tests/data/typing/partial.fa +19 -0
- gapit-0.5.0/tests/data/typing/schemes/cholerae.gbk +153 -0
- gapit-0.5.0/tests/data/typing/schemes/cholerae.json +58 -0
- gapit-0.5.0/tests/data/typing/schemes/dec.fa +144 -0
- gapit-0.5.0/tests/data/typing/schemes/dec.json +125 -0
- gapit-0.5.0/tests/data/typing/schemes/doumith.fa +49 -0
- gapit-0.5.0/tests/data/typing/schemes/doumith.json +42 -0
- gapit-0.5.0/tests/data/typing/schemes/meningotype.fa +66 -0
- gapit-0.5.0/tests/data/typing/schemes/meningotype.json +60 -0
- gapit-0.5.0/tests/data/typing/schemes/shigella.fa +151 -0
- gapit-0.5.0/tests/data/typing/schemes/shigella.json +74 -0
- gapit-0.5.0/tests/data/typing/schemes/vp_ok.gbk +241 -0
- gapit-0.5.0/tests/data/typing/schemes/vp_ok.json +66 -0
- gapit-0.5.0/tests/data/typing/serotyping.fa +99 -0
- gapit-0.5.0/tests/data/typing/typing_markers_v1.json +22 -0
- gapit-0.5.0/tests/data/typing/typing_markers_v2.json +47 -0
- gapit-0.5.0/tests/data/typing/typing_serotyping_v2.json +71 -0
- gapit-0.5.0/tests/data/typing/vp_mixed.fa +39 -0
- gapit-0.5.0/tests/data/typing/vp_typed.fa +19 -0
- gapit-0.5.0/tests/golden/cluster_exact.json +72 -0
- gapit-0.5.0/tests/golden/cluster_exact.md +28 -0
- gapit-0.5.0/tests/golden/cluster_exact.tsv +2 -0
- gapit-0.5.0/tests/golden/cluster_fragmented.json +72 -0
- gapit-0.5.0/tests/golden/cluster_fragmented.md +28 -0
- gapit-0.5.0/tests/golden/cluster_fragmented.tsv +2 -0
- gapit-0.5.0/tests/golden/cluster_typing_ambiguous.json +133 -0
- gapit-0.5.0/tests/golden/cluster_typing_ambiguous.md +30 -0
- gapit-0.5.0/tests/golden/cluster_typing_ambiguous.tsv +2 -0
- gapit-0.5.0/tests/golden/cluster_typing_cm_exact.json +95 -0
- gapit-0.5.0/tests/golden/cluster_typing_cm_exact.md +30 -0
- gapit-0.5.0/tests/golden/cluster_typing_cm_exact.tsv +2 -0
- gapit-0.5.0/tests/golden/cluster_typing_exact.json +95 -0
- gapit-0.5.0/tests/golden/cluster_typing_exact.md +30 -0
- gapit-0.5.0/tests/golden/cluster_typing_exact.tsv +2 -0
- gapit-0.5.0/tests/golden/cluster_vc_inaba.json +95 -0
- gapit-0.5.0/tests/golden/cluster_vc_inaba.md +30 -0
- gapit-0.5.0/tests/golden/cluster_vc_inaba.tsv +2 -0
- gapit-0.5.0/tests/golden/ecoli_dec_typed.tsv +8 -0
- gapit-0.5.0/tests/golden/ecoli_dec_typing.tsv +5 -0
- gapit-0.5.0/tests/golden/fragments_merge.json +100 -0
- gapit-0.5.0/tests/golden/fragments_merge.md +30 -0
- gapit-0.5.0/tests/golden/fragments_merge.tsv +3 -0
- gapit-0.5.0/tests/golden/gene_dec_pic_astA.json +69 -0
- gapit-0.5.0/tests/golden/gene_dec_pic_astA.md +20 -0
- gapit-0.5.0/tests/golden/gene_doumith_4b.json +69 -0
- gapit-0.5.0/tests/golden/gene_doumith_4b.md +20 -0
- gapit-0.5.0/tests/golden/gene_serotyping_l4b.json +69 -0
- gapit-0.5.0/tests/golden/gene_serotyping_l4b.md +20 -0
- gapit-0.5.0/tests/golden/gene_serotyping_mixed.json +85 -0
- gapit-0.5.0/tests/golden/gene_serotyping_mixed.md +21 -0
- gapit-0.5.0/tests/golden/gene_serotyping_vp_typed.json +53 -0
- gapit-0.5.0/tests/golden/gene_serotyping_vp_typed.md +19 -0
- gapit-0.5.0/tests/golden/gene_shigella_mixed.json +101 -0
- gapit-0.5.0/tests/golden/gene_shigella_mixed.md +22 -0
- gapit-0.5.0/tests/golden/gene_typing_exact.json +85 -0
- gapit-0.5.0/tests/golden/gene_typing_exact.md +21 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/golden/reads_tinyamr.json +1 -1
- {gapit-0.3.1 → gapit-0.5.0}/tests/golden/reads_tinyamr.md +1 -1
- {gapit-0.3.1 → gapit-0.5.0}/tests/golden/screen_multi.json +1 -1
- {gapit-0.3.1 → gapit-0.5.0}/tests/golden/screen_multi.md +1 -3
- {gapit-0.3.1 → gapit-0.5.0}/tests/golden/summary_multi.json +1 -1
- {gapit-0.3.1 → gapit-0.5.0}/tests/golden/summary_multi.md +1 -1
- gapit-0.5.0/tests/golden/typing_markers.json +141 -0
- gapit-0.5.0/tests/golden/typing_markers.md +20 -0
- gapit-0.5.0/tests/golden/typing_markers.tsv +7 -0
- gapit-0.5.0/tests/golden/typing_serotyping.tsv +21 -0
- gapit-0.5.0/tests/parity/corpus/04_reverse.fa +42 -0
- gapit-0.5.0/tests/parity/corpus/05_threshold.fa +32 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/parity/make_corpus.py +52 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/parity/run_parity.py +5 -2
- gapit-0.5.0/tests/test_bundled.py +481 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_cli_aligner.py +1 -1
- gapit-0.5.0/tests/test_cli_bare_help.py +126 -0
- gapit-0.5.0/tests/test_cli_db_build_cluster.py +247 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_cli_db_fetch.py +143 -108
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_cli_db_query.py +14 -46
- gapit-0.5.0/tests/test_cli_fragments.py +190 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_cli_reads.py +36 -3
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_cli_reads2.py +1 -1
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_cli_screen.py +209 -2
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_cli_setupdb.py +50 -17
- gapit-0.5.0/tests/test_cli_short_options.py +388 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_cli_summary.py +5 -3
- gapit-0.5.0/tests/test_cluster_calibration.py +152 -0
- gapit-0.5.0/tests/test_cluster_db.py +125 -0
- gapit-0.5.0/tests/test_cluster_math.py +141 -0
- gapit-0.5.0/tests/test_cluster_screen.py +574 -0
- gapit-0.5.0/tests/test_cluster_typing.py +379 -0
- gapit-0.5.0/tests/test_db_list_extras.py +169 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_error_envelope.py +15 -2
- gapit-0.5.0/tests/test_fragments.py +293 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_gapit_db_e2e.py +2 -1
- gapit-0.5.0/tests/test_gbfeatures.py +133 -0
- gapit-0.5.0/tests/test_gene_typing.py +530 -0
- gapit-0.5.0/tests/test_gene_typing2.py +389 -0
- gapit-0.5.0/tests/test_gffparse.py +113 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_json_format.py +7 -1
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_mcp.py +50 -1
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_mcp_db_tools.py +67 -48
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_mcp_reads.py +17 -2
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_md_format.py +1 -4
- gapit-0.5.0/tests/test_provider_kaptive.py +236 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_providers_common.py +27 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_reads2_homologs.py +1 -1
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_reads2_model.py +1 -1
- gapit-0.5.0/tests/test_streaming_chunks.py +522 -0
- gapit-0.5.0/tests/test_typing_command.py +654 -0
- gapit-0.5.0/tests/test_typing_engine.py +679 -0
- gapit-0.5.0/tests/test_typing_models.py +678 -0
- gapit-0.5.0/tests/test_typing_schemes.py +663 -0
- gapit-0.5.0/tests/test_typing_schemes_cluster.py +320 -0
- gapit-0.5.0/tests/test_typing_stage2.py +509 -0
- gapit-0.3.1/.github/workflows/snapshot-refresh.yml +0 -129
- gapit-0.3.1/CHANGELOG.md +0 -148
- gapit-0.3.1/docs/databases.md +0 -529
- gapit-0.3.1/docs/screen.md +0 -205
- gapit-0.3.1/mkdocs.yml +0 -36
- gapit-0.3.1/recipe/meta.yaml +0 -74
- gapit-0.3.1/src/gapit/cmd_db.py +0 -113
- gapit-0.3.1/src/gapit/cmd_db_build.py +0 -72
- gapit-0.3.1/src/gapit/cmd_screen.py +0 -214
- gapit-0.3.1/src/gapit/data/snapshots/card.tar.gz +0 -0
- gapit-0.3.1/src/gapit/data/snapshots/vfdb.tar.gz +0 -0
- gapit-0.3.1/src/gapit/db_ops.py +0 -128
- gapit-0.3.1/src/gapit/dispatch.py +0 -31
- gapit-0.3.1/src/gapit/formats/tsv.py +0 -45
- gapit-0.3.1/src/gapit/hits.py +0 -107
- gapit-0.3.1/src/gapit/providers/__init__.py +0 -39
- gapit-0.3.1/src/gapit/providers/snapshots.py +0 -119
- gapit-0.3.1/src/gapit/screening.py +0 -145
- gapit-0.3.1/tests/test_snapshots.py +0 -204
- {gapit-0.3.1 → gapit-0.5.0}/.gitattributes +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/.github/workflows/ci.yml +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/.github/workflows/docs.yml +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/.github/workflows/release.yml +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/.gitignore +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/LICENSE +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/docs/custom-db.md +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/config.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/dbcodec.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/errors.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/fasta.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/formats/__init__.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/formats/summary.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/mcp.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/minimap.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/proctools.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/py.typed +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/reads.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/seqconvert.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/src/gapit/summary.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/contigs/full.fa +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/contigs/gap.fa +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/contigs/none.fa +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/contigs/partial.fa +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/contigs/sort.fa +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/convert/sample.embl +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/convert/sample.embl.bz2 +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/convert/sample.fa +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/convert/sample.fa.gz +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/convert/sample.fq +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/convert/sample.gbk +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/convert/sample.gbk.gz +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/db/tinyamr/sequences +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/providers/argannot/ARG-ANNOT_NT_V6_July2019.txt +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/providers/bacmet2/BacMet2_EXP_database.fasta +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/providers/card/card.json +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/providers/ecoh/EcOH.fasta +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/providers/ecoli_vf/repaired_ecoli_vfs_shortnames.ffn +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/providers/megares/megares_drugs_demo.fasta +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/providers/ncbi/AMR_CDS.fa +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/providers/ncbi/ReferenceGeneCatalog.txt +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/providers/plasmidfinder/plasmids_a.fsa +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/providers/plasmidfinder/plasmids_b.fsa +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/providers/resfinder/aminoglycoside.fsa +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/providers/resfinder/beta-lactam.fsa +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/providers/resfinder/phenotypes.txt +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/providers/upec_expec_vf/UPEC_ExPEC_VF.tsv +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/providers/vfdb/VFDB_setA_nt.fas +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/providers/victors/gen_downloads.php +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/providers/victors/gen_downloads_protein.php +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/reads/bla_partial.fq +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/reads/junk.fq +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/reads/suly_partial.fq +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/reads/tetx_R1.fq +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/reads/tetx_R2.fq +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/reads/tetx_full.fq +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/reads/tetx_full.fq.gz +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/reads/tetx_lane1.fq +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/reads/tetx_lane2.fq +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/reads/tetx_pe1_R1.fq +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/reads/tetx_pe1_R2.fq +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/reads/tetx_pe2_R1.fq +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/reads/tetx_pe2_R2.fq +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/reads2/ont_homologs.fq +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/reads2/sr_homologs.fq +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/reads2_db/homologs/sequences +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/reads_db/tinyreads/sequences +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/summary/empty.tsv +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/summary/multi_sample.tsv +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/summary/sample_a.csv +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/summary/sample_a.tsv +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/summary/sample_b.csv +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/data/summary/sample_b.tsv +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/golden/summary_dutch.tsv +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/golden/summary_multi.csv +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/golden/summary_multi.tsv +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/golden/tinyamr_multi_nopath.csv +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/golden/tinyamr_multi_nopath.tsv +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/parity/corpus/01_exact_and_junk.fa +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/parity/corpus/02_mutated.fa +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/parity/corpus/03_truncated.fa +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/parity/run_summary_parity.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_blast_parse.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_blast_pipeline.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_cli_completion.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_cli_db_build.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_cli_schema.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_cli_screen_jobs.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_config.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_db.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_db_fetch.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_db_headers.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_dbbuild.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_dbcodec.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_fasta.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_hits.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_mcp_protocol.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_minimap.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_mol_type.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_oversubscription.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_paf.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_paf_identity.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_provider_argannot.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_provider_bacmet2.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_provider_card.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_provider_ecoh.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_provider_ecoli_vf.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_provider_megares.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_provider_ncbi.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_provider_plasmidfinder.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_provider_resfinder.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_provider_upec_expec_vf.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_provider_vfdb.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_provider_victors.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_reads_aggregate.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_reads_integration.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_reads_interval_union.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_reads_streaming.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_records.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_report.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_screen_integration.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_screening_reads_unit.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_seqconvert.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_seqconvert_differential.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_summary.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_summary_formats.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_tsv.py +0 -0
- {gapit-0.3.1 → gapit-0.5.0}/tests/test_version.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# AGENTS.md — gapit
|
|
2
2
|
|
|
3
3
|
> Python reimplementation of [abricate](https://github.com/tseemann/abricate): mass screening of
|
|
4
|
-
> contigs
|
|
4
|
+
> contigs and reads for known genes. **Agent-first**: every output is
|
|
5
5
|
> machine-readable (JSON / Markdown) by design, not as an afterthought.
|
|
6
6
|
|
|
7
7
|
## 1. Mission
|
|
@@ -62,7 +62,7 @@ gapit/
|
|
|
62
62
|
│ ├── __init__.py
|
|
63
63
|
│ ├── cli.py # typer entrypoint: screen / summary / db / setupdb / schema / mcp
|
|
64
64
|
│ ├── config.py # datadir resolution, defaults, env vars
|
|
65
|
-
│ ├── dispatch.py # shared CLI dispatch (error envelope → exit codes) + --datadir option
|
|
65
|
+
│ ├── dispatch.py # shared CLI dispatch (error envelope → exit codes) + --datadir option + --output target
|
|
66
66
|
│ ├── proctools.py # external-tool plumbing: argv subprocess runner + stderr notes
|
|
67
67
|
│ ├── fasta.py # streaming FASTA reader + shared gz/bz2 text opener
|
|
68
68
|
│ ├── seqconvert.py # native input normalization: fa/fq/gbk/embl (±gz/bz2) → FASTA
|
|
@@ -70,21 +70,40 @@ gapit/
|
|
|
70
70
|
│ ├── dbcodec.py # gapit/v1 tagged-header codec (percent-encoded ids)
|
|
71
71
|
│ ├── records.py # records.jsonl truth store + gapit.manifest/1 provenance
|
|
72
72
|
│ ├── dbbuild.py # deterministic native-db build pipeline with self-check
|
|
73
|
-
│ ├──
|
|
73
|
+
│ ├── clusterbuild.py # cluster-db build pipeline: GBK/GFF → locus FASTA + features.json + typing copy
|
|
74
|
+
│ ├── cluster.py # cluster-screening engine core: minimap2 asm20 → per-locus/per-gene calls
|
|
75
|
+
│ ├── cluster_math.py # cs-walk → union coverage/identity math + verdicts (pure functions)
|
|
76
|
+
│ ├── db_ops.py # db use-cases: fetch + list (shared CLI + MCP; no typer)
|
|
74
77
|
│ ├── db_query_ops.py # db use-cases: search + outdated over installed DBs (shared CLI + MCP)
|
|
75
|
-
│ ├── db_build_ops.py # db use-case: custom FASTA+TSV →
|
|
78
|
+
│ ├── db_build_ops.py # db use-case: custom FASTA+TSV → gene db, GBK/GFF → cluster db (shared CLI + MCP)
|
|
79
|
+
│ ├── gbfeatures.py # GenBank FEATURES/ORIGIN parser → LocusFeatures/GeneFeature + gapit.features/1
|
|
80
|
+
│ ├── gffparse.py # GFF3 parser (embedded ##FASTA or sidecar) → the same locus/gene models
|
|
81
|
+
│ ├── typing_models.py # gapit.typing schema (rules + named schemes; /1 degrades to one default scheme)
|
|
82
|
+
│ ├── typing_rules.py # gapit.typing rule models (weighted_genes/exact_set/cluster_match/learned_linear) + reference checks
|
|
83
|
+
│ ├── typing_decide.py # typing decision layer: ranking, control-gene gate, unique-group mixed override
|
|
84
|
+
│ ├── typing_results.py # typing evaluation-result models (PhenotypeDetail, SchemeCall)
|
|
85
|
+
│ ├── typing_engine.py # typing evaluation, cluster path: rule scoring → phenotype call + breakdown
|
|
86
|
+
│ ├── typing_gene.py # typing evaluation, gene path (DEC markers): hits → per-scheme report phenotypes
|
|
87
|
+
│ ├── bundled.py # bundled databases: discovery + materialize-into-datadir (public-domain panels)
|
|
76
88
|
│ ├── blast.py # blastn invocation + tabular output parsing
|
|
77
89
|
│ ├── hits.py # Hit model, identity/coverage computation, filtering, dedup
|
|
90
|
+
│ ├── fragments.py # opt-in --merge-fragments cross-contig gene-fragment merging
|
|
78
91
|
│ ├── minimap.py # COVERAGE_MAP construction (exact abricate arithmetic)
|
|
79
92
|
│ ├── minimap2_run.py # minimap2 invocation layer for reads mode (streaming PAF, --cs/NM tags)
|
|
80
93
|
│ ├── paf.py # PAF row parsing + interval arithmetic (minimap2 output boundary)
|
|
81
94
|
│ ├── report.py # Report model: the canonical in-memory result
|
|
82
|
-
│ ├──
|
|
95
|
+
│ ├── engines.py # shared OutputFormat / AlignerEnum (leaf module for the three engines)
|
|
96
|
+
│ ├── screening.py # blastn screen use-case + the shared run_screen dispatcher
|
|
97
|
+
│ ├── screening_cluster.py # cluster screen use-case: kind guards, typing wiring, rendering
|
|
83
98
|
│ ├── screening_reads.py # minimap2 use-cases: --r1/--r2 reads + --aligner minimap2 assemblies
|
|
84
|
-
│ ├──
|
|
99
|
+
│ ├── typing_input.py # `gapit typing` input: screen TSV/CSV → per-FILE folded GeneCalls
|
|
100
|
+
│ ├── typing_ops.py # `gapit typing` use-case: resolve db, run the engine, render
|
|
101
|
+
│ ├── reads.py # FASTQ mode: minimap2 PAF parsing, coverage breadth/depth, presence
|
|
85
102
|
│ ├── summary.py # summary core: parse report tables into a gene matrix
|
|
86
103
|
│ ├── cmd_screen.py # `gapit screen` CLI (registered from cli.py)
|
|
104
|
+
│ ├── cmd_screen_reads_args.py # reads-mode CLI arg rules (comma split + flag rejects)
|
|
87
105
|
│ ├── cmd_summary.py # `gapit summary` CLI (registered from cli.py)
|
|
106
|
+
│ ├── cmd_typing.py # `gapit typing` CLI (registered from cli.py)
|
|
88
107
|
│ ├── cmd_db.py # `gapit db` command group (fetch | list; registers the subcommands)
|
|
89
108
|
│ ├── cmd_db_install.py # `gapit db install`: SHA256-verified local-file install
|
|
90
109
|
│ ├── cmd_db_build.py # `gapit db build` CLI (custom FASTA → native db)
|
|
@@ -95,14 +114,19 @@ gapit/
|
|
|
95
114
|
│ ├── mcp_schemas.py # MCP tools/list declarations (names, descriptions, inputSchemas)
|
|
96
115
|
│ ├── errors.py # typed errors + JSON error envelope
|
|
97
116
|
│ ├── formats/
|
|
98
|
-
│ │ ├── tsv.py # abricate-compatible TSV/CSV
|
|
117
|
+
│ │ ├── tsv.py # abricate-compatible TSV/CSV (phenotype-free in every typing version)
|
|
99
118
|
│ │ ├── json.py # versioned JSON (gapit.report/1 et al.)
|
|
119
|
+
│ │ ├── reads_json.py # versioned JSON (gapit.reads/1, gapit.reads/2)
|
|
100
120
|
│ │ ├── md.py # Markdown (human + agent readable, YAML frontmatter)
|
|
121
|
+
│ │ ├── cluster.py # gapit.cluster/1 models + JSON/TSV renderers (typed variant)
|
|
122
|
+
│ │ ├── cluster_md.py # gapit.cluster/1 Markdown renderer (Phenotype column when typed)
|
|
123
|
+
│ │ ├── typing_result.py # gapit.typing_result/1 models + TSV/JSON/MD renderers
|
|
101
124
|
│ │ ├── schemas.py # registered output models behind `gapit schema`
|
|
102
125
|
│ │ └── summary.py # summary matrix renderers (TSV/CSV/JSON/MD)
|
|
103
|
-
│ ├── providers/ # 12
|
|
104
|
-
│ ├── data/snapshots/ # bundled card + vfdb snapshot archives (.tar.gz)
|
|
126
|
+
│ ├── providers/ # 19 database provider modules (12 gene + 7 kaptive cluster) + cluster_common.py + common.py
|
|
105
127
|
│ └── py.typed
|
|
128
|
+
├── scripts/
|
|
129
|
+
│ └── cluster_calibration.py # developer calibration harness for typed cluster dbs
|
|
106
130
|
└── tests/
|
|
107
131
|
├── data/ # tiny synthetic db + contigs + reads (fast, offline)
|
|
108
132
|
├── golden/ # expected outputs incl. abricate reference TSVs
|
|
@@ -131,7 +155,8 @@ This is what distinguishes gapit from abricate. Treat it as a public API.
|
|
|
131
155
|
|
|
132
156
|
- **Formats**: `--format tsv|csv|json|md` (default `tsv` for abricate compatibility).
|
|
133
157
|
- **JSON**: top-level `"schema": "gapit.report/1"`; schema introspectable via
|
|
134
|
-
`gapit schema report | reads | reads2 | summary | list | error | version
|
|
158
|
+
`gapit schema report | reads | reads2 | summary | list | error | version` (plus
|
|
159
|
+
`cluster | features | typing | typing_result`). Keys are snake_case,
|
|
135
160
|
units explicit (`identity_pct`, `coverage_pct`). Semver the schema; never rename or
|
|
136
161
|
retype a field in a minor bump.
|
|
137
162
|
- **Markdown**: YAML frontmatter (tool version, db, params, ISO-8601 UTC timestamp) + tables a
|
|
@@ -139,14 +164,30 @@ This is what distinguishes gapit from abricate. Treat it as a public API.
|
|
|
139
164
|
- **Errors**: failures print a JSON envelope to stderr
|
|
140
165
|
`{"schema": "gapit.error/1", "code": "...", "message": "...", "context": {...}}` and exit with a
|
|
141
166
|
documented non-zero code (2 = usage, 3 = missing dependency, 4 = db error, 5 = input error).
|
|
167
|
+
- **Typing** `[gapit-extension]`: two-stage designation — `gapit screen -o result.tsv --db NAME`
|
|
168
|
+
detects genes (screen output is phenotype-free; typed and untyped gene dbs screen
|
|
169
|
+
byte-identically), then `gapit typing result.tsv [-D|-f|-o|-q]` designates from the screen
|
|
170
|
+
table (`gapit.typing_result/1`; cluster dbs refuse — their typing rides the screen).
|
|
171
|
+
No typing MCP tool yet (future work).
|
|
142
172
|
- **DB acquisition** `[gapit-extension]`: `gapit db fetch|list|search|outdated|build|install` —
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
173
|
+
database fetch from the provider catalog (every provider downloads from upstream at fetch
|
|
174
|
+
time — nothing catalog-side is bundled inside the wheel beyond the sanctioned exceptions,
|
|
175
|
+
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
|
|
177
|
+
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),
|
|
182
|
+
database listing,
|
|
183
|
+
records.jsonl gene search, staleness
|
|
184
|
+
report, custom FASTA→native-db build, GBK/GFF→cluster-db build (`--typing` installs a
|
|
185
|
+
validated `gapit.typing/1` or `/2` spec on either kind), the four download-on-fetch kaptive cluster providers
|
|
186
|
+
(GPL content, never bundled), and SHA256-verified local-file install.
|
|
146
187
|
- **MCP** `[gapit-extension]`: `gapit mcp` / `gapit-mcp` stdio server exposing nine tools:
|
|
147
188
|
read-only `screen` (incl. `aligner minimap2` assembly survey), `screen_reads` (FASTQ via
|
|
148
189
|
minimap2), `summary`, `schema`, `db_list`, `db_search`, `db_outdated`, plus the datadir-mutating
|
|
149
|
-
`db_fetch` (installs provider
|
|
190
|
+
`db_fetch` (installs databases from the provider catalog; may download) and `db_build` (writes a custom db);
|
|
150
191
|
tool failures carry the `gapit.error/1` envelope.
|
|
151
192
|
- **stdout purity**: data on stdout, diagnostics on stderr, always. `--quiet` only affects stderr.
|
|
152
193
|
- **Self-description**: `gapit --version --json`, `gapit db list --json`, `gapit schema` — an agent
|
|
@@ -175,7 +216,9 @@ This is what distinguishes gapit from abricate. Treat it as a public API.
|
|
|
175
216
|
query contigs against one db → 15-field
|
|
176
217
|
tabular hits → filter by identity / coverage thresholds → **dedup hits sharing identical
|
|
177
218
|
`(contig, qstart, qend)`** (first/best BLAST row wins) → one TSV row per surviving hit.
|
|
178
|
-
abricate
|
|
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`).
|
|
179
222
|
- Key computed fields: `%COVERAGE = 100*(length-gaps)/slen` (filtered unrounded, displayed
|
|
180
223
|
`%.2f`), `%IDENTITY` (BLAST pident, never post-filtered), `COVERAGE_MAP` (15-char minimap),
|
|
181
224
|
`GAPS`. Exact formulas, the dedup rule, and the minimap arithmetic live in `SPEC.md` — when
|
gapit-0.5.0/CHANGELOG.md
ADDED
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to gapit are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this
|
|
6
|
+
project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.5.0] - 2026-10-02
|
|
9
|
+
|
|
10
|
+
### Breaking
|
|
11
|
+
|
|
12
|
+
- **`--format md` now streams per file, and the Markdown layout lost its run totals (MD goldens
|
|
13
|
+
and docs regenerated).** The Markdown frontmatter was dynamic — `files:`/`hits:` counts (and
|
|
14
|
+
the cluster report's all-files summary table) only exist once every file has screened, which
|
|
15
|
+
forced the renderer to buffer the whole document until the end. The frontmatter is now STATIC
|
|
16
|
+
metadata only (`schema`, `tool`, `created_at`, `db`, thresholds — everything knowable before
|
|
17
|
+
file 1): it prints first and each file's section (heading, table, merge-fragment lines; on
|
|
18
|
+
cluster databases the file's own summary row plus its gene table, replacing the global summary
|
|
19
|
+
table) prints the moment that file completes — head-of-line in input order under `--jobs`,
|
|
20
|
+
exactly like the tsv rows, with `--output` flushing per chunk. Run totals now live only in the
|
|
21
|
+
JSON document (`gapit.report/1` `files[]`/`hits`, `gapit.cluster/1`), which stays a single
|
|
22
|
+
buffered document by design. Update any parser that read `files:`/`hits:` from Markdown
|
|
23
|
+
frontmatter or expected the cluster summary table above the sections; per-file content is
|
|
24
|
+
unchanged byte-for-byte. Reads-mode Markdown (one document per run by construction) and
|
|
25
|
+
`gapit typing`'s Markdown are unchanged.
|
|
26
|
+
|
|
27
|
+
- **`gapit screen --db` is now required (no default).** The silent `ncbi` default could
|
|
28
|
+
auto-materialize a bundled 8.4k-record database as a hidden side effect of a bare
|
|
29
|
+
`gapit screen contigs.fa`; a screen now refuses to run (typer usage error, exit 2) until
|
|
30
|
+
`--db NAME` is given explicitly. The MCP `screen`/`screen_reads` tools mirror the change:
|
|
31
|
+
`db` moved into each inputSchema's `required` array (default removed), and an absent
|
|
32
|
+
`db` returns the `gapit.error/1` USAGE_ERROR envelope. Update any invocation that relied
|
|
33
|
+
on the default.
|
|
34
|
+
- **`gapit screen` no longer embeds phenotypes — designation moved to the new `gapit typing`
|
|
35
|
+
command (one-cycle revert; the embedded surfaces never released).** Screening a typed gene
|
|
36
|
+
database is now pure gene detection, byte-identical to screening an untyped one in every
|
|
37
|
+
format: the earlier-this-cycle `PHENOTYPE` column on the report TSV/CSV, the
|
|
38
|
+
`files[].phenotypes` object of `gapit.report/1`, and the Markdown phenotype lines are all
|
|
39
|
+
gone (the typing engine itself — rules, schemes, gates, compose — is unchanged, and
|
|
40
|
+
`typing.json` still ships with databases). The reads-mode guard that rejected typed gene
|
|
41
|
+
dbs (`gene-path typing is contig-mode only`) is gone with it: `--r1/--r2` and
|
|
42
|
+
`--aligner minimap2` screen typed gene databases like any other. The cluster path is
|
|
43
|
+
untouched — typed cluster databases keep their integrated designation (the
|
|
44
|
+
`gapit.cluster/1` phenotype block and the typed-only TSV `PHENOTYPE` column). The MCP
|
|
45
|
+
`screen` tool returns the pure report on typed gene dbs (a typing MCP tool is future
|
|
46
|
+
work). If you consumed `files[].phenotypes` from pre-release builds, switch to
|
|
47
|
+
`gapit typing` (below).
|
|
48
|
+
|
|
49
|
+
### Added
|
|
50
|
+
|
|
51
|
+
- **`gapit typing RESULT.tsv [RESULT2.tsv ...]` — designation from screen results (the
|
|
52
|
+
rightsholder's two-stage CLI design).** Stage 1: `gapit screen -o result.tsv --db NAME`
|
|
53
|
+
detects genes; stage 2: `gapit typing result.tsv` reads the gapit/abricate screen table
|
|
54
|
+
(TSV or auto-detected CSV, several tables merge by their FILE column), resolves NAME from
|
|
55
|
+
the rows' shared `DATABASE` column under `--datadir` (bundled databases still materialize
|
|
56
|
+
on first use), folds every `(FILE, GENE)` to its best row by `(%IDENTITY, %COVERAGE)`
|
|
57
|
+
(first row wins ties — the same per-gene fold the report hits received), and runs the
|
|
58
|
+
existing typing engine over each FILE's genes. Output: default TSV with columns `FILE`,
|
|
59
|
+
`SCHEME`, `PHENOTYPE`, `CONFIDENCE`, `SCORE`, `RUNNER_UP`, `NOTES` (ambiguous calls
|
|
60
|
+
render `-` and carry the candidate pair in NOTES; streamed per input file), `--format
|
|
61
|
+
json` as the new versioned **`gapit.typing_result/1`** document (`{schema, tool,
|
|
62
|
+
created_at, source, db, files[].phenotypes}` — full score breakdowns, introspectable via
|
|
63
|
+
`gapit schema typing_result`, also registered in the MCP `schema` tool), and
|
|
64
|
+
`--format md` (frontmatter + the same seven-column table); `-o FILE`/`-q` behave as
|
|
65
|
+
everywhere. Typed errors: mixed `DATABASE` values `DATABASE_MISMATCH`, a table with no
|
|
66
|
+
data rows `TYPING_NO_DATA` (a screened-no-hits file has no rows — the database is only
|
|
67
|
+
knowable from them), a database without a `typing.json` `TYPING_NO_SCHEME`, and a cluster
|
|
68
|
+
database `TYPING_CLUSTER_DB` (its typing is integrated in `gapit screen`). Equivalence is
|
|
69
|
+
locked end to end: the DEC matrix, serotyping fixtures, and the bundled `ecoli_dec`
|
|
70
|
+
assert the command's calls equal the calls the inline engine produced before the move,
|
|
71
|
+
with new goldens (`typing_markers.*`, `typing_serotyping.tsv`, `ecoli_dec_typing.tsv`).
|
|
72
|
+
The table also arrives on stdin: `gapit screen 1.fna --db NAME | gapit typing` types the
|
|
73
|
+
piped output with no file arguments (stdin must not be a terminal — a bare invocation at
|
|
74
|
+
a terminal still prints help), the explicit `gapit typing -` marker reads stdin even
|
|
75
|
+
under a terminal (until EOF), mixing `-` with file arguments is a usage error (v1:
|
|
76
|
+
either stdin or files), a piped table's JSON `source` renders as `["-"]`, and an empty
|
|
77
|
+
pipe is the usual `TYPING_NO_DATA` naming `-`. The three delivery forms (file, `-`,
|
|
78
|
+
pipe) are locked byte-identical.
|
|
79
|
+
- **Short single-dash aliases for every CLI option (rightsholder UX directive).** Each option
|
|
80
|
+
on every command now pairs a short form with its long form — `--help`/`-h` style, e.g.
|
|
81
|
+
`gapit screen contigs.fa -d ncbi -f json` for `--db ncbi --format json`. Letters follow the
|
|
82
|
+
first-letter convention with uppercase on collision (`--db`/`-d` vs `--datadir`/`-D`;
|
|
83
|
+
`--minid`/`-i` vs `--min-identity`/`-I`), mnemonics where the first letter is taken
|
|
84
|
+
(`--min-gene-cov`/`-g`, `--read-type`/`-x`, `--r1`/`-1`), and `-v` for `--debug` (verbose).
|
|
85
|
+
Deliberate exceptions: boolean negative halves stay long-only (`--no-merge-fragments`) and
|
|
86
|
+
the typer-managed completion flags are untouched. Long forms are unchanged and remain the
|
|
87
|
+
documented canonical spelling; a regression test walks the built command tree proving every
|
|
88
|
+
option has a unique per-command short and byte-compares short vs long invocations.
|
|
89
|
+
- **`gapit screen --output PATH` writes the report to a file (all engines, including
|
|
90
|
+
reads mode).** The file opens on the first output byte — truncating any existing file
|
|
91
|
+
(v1 overwrite semantics, never append) — every streamed chunk is flushed, and stdout
|
|
92
|
+
then carries no data (stderr diagnostics unchanged). An in-batch failure on file *k*
|
|
93
|
+
leaves files 1..*k-1*'s already-streamed output persisted in the file (or printed, on
|
|
94
|
+
stdout) before the typed error envelope and documented exit code; a run failing before
|
|
95
|
+
any output (usage/dependency/db errors) creates no file.
|
|
96
|
+
- **Per-file streaming emission for tsv/csv.** `gapit screen` (blastn gene path and
|
|
97
|
+
cluster path) now emits results in input order as each file completes instead of
|
|
98
|
+
buffering everything until the end: the TSV/CSV header prints once screening starts and
|
|
99
|
+
each file's rows print the moment its file finishes — head-of-line under `--jobs N > 1`
|
|
100
|
+
(file *i* waits for 1..*i*, so output bytes stay identical to sequential runs).
|
|
101
|
+
Markdown sections are computed per file but the document (frontmatter totals) is emitted
|
|
102
|
+
once at the end; JSON stays a single buffered document. Chunk concatenation is
|
|
103
|
+
byte-identical to the former buffered render — goldens and abricate parity are
|
|
104
|
+
untouched. The use-cases gained an optional `emit: Callable[[str], None]` sink (default
|
|
105
|
+
`None` = buffered return exactly as before, so MCP and library callers are unchanged).
|
|
106
|
+
|
|
107
|
+
- **Bundled databases — four audited provider snapshots join `ecoli_dec` in the wheel
|
|
108
|
+
(five bundles total).** `ncbi` (8373 records, public domain), `resfinder` (3206,
|
|
109
|
+
Apache-2.0), `ecoh` (597, BSD-3-Clause), and `upec_expec_vf` (77, MIT) now ship under
|
|
110
|
+
`src/gapit/data/dbs/<name>/` as point-in-time snapshots produced by the `db fetch`
|
|
111
|
+
provider pipeline itself (gapit/v1 headers; snapshot date recorded in `bundled.json`
|
|
112
|
+
as `snapshotted`, the metadata model's new field). `db fetch <name>` remains the
|
|
113
|
+
fresh-upstream update path for all four: it re-downloads the latest upstream content
|
|
114
|
+
and (with `--force`) overwrites the materialized datadir copy, whose manifest then
|
|
115
|
+
drops the `bundled` source stamp; a regression test pins the snapshot↔fetch
|
|
116
|
+
byte-identity for `resfinder` against a committed copy of the exact upstream archive,
|
|
117
|
+
and the provenance guard now scans ALL five bundles' headers for `VF*`/`VFDB`/`ARO:`
|
|
118
|
+
markers. `db list` merges registry-and-bundled names into ONE bundled-section row
|
|
119
|
+
(STATUS `bundled` → `installed (N)`; JSON `source: "bundled"`); registry rows for
|
|
120
|
+
non-bundled providers stay byte-identical. Wheel size 170 KiB → 1.5 MiB (+1.3 MiB for
|
|
121
|
+
the four snapshots; their `sequences` are ~13 MiB uncompressed). `db outdated` stays
|
|
122
|
+
manifest-based (bundled-vs-upstream staleness comparison is future work).
|
|
123
|
+
- **Bundled databases — `ecoli_dec` ships install-time ready (zero-network first use).**
|
|
124
|
+
A new mechanism (`gapit.bundled`) lets license-clean, public-domain databases ride the
|
|
125
|
+
wheel under `src/gapit/data/dbs/<name>/` (`sequences` + optional `typing.json` +
|
|
126
|
+
`bundled.json` metadata: name, description, vendor, dbtype). The first database to use
|
|
127
|
+
it is `ecoli_dec`: the 17-record diarrheagenic E. coli marker panel with the dual-scheme
|
|
128
|
+
`gapit.typing/2` designation (gb4789_6 + risk_monitoring) — after the 2026-10 provenance
|
|
129
|
+
audit re-sourced all records to NCBI/DDBJ primary submissions. When `--db` names a
|
|
130
|
+
bundled database that is absent from the datadir, the screen path materializes it first
|
|
131
|
+
(one quiet-respecting stderr note, then the standard gene-build pipeline: records.jsonl,
|
|
132
|
+
gapit/v1 sequences, BLAST index, typing copy, manifest stamped with the additive
|
|
133
|
+
`source: "bundled"` field); a completely missing datadir is bootstrapped on this path
|
|
134
|
+
only. `gapit setupdb` materializes every bundled database alongside indexing; both paths
|
|
135
|
+
are idempotent (no-op once the manifest exists). `db list` gains a bundled section
|
|
136
|
+
between the registry rows and local extras on all four surfaces (TSV, rich table,
|
|
137
|
+
`--json`, MCP `db_list`): STATUS `bundled` before materialization, `installed (N)`
|
|
138
|
+
after, JSON `source: "bundled"` — registry and local rows stay byte-identical. Wheel
|
|
139
|
+
size 159 KiB → 170 KiB (+11 KiB for the panel).
|
|
140
|
+
- **DEC dual-scheme designation + the `requires_any` exact_set primitive.** The
|
|
141
|
+
diarrheagenic E. coli placeholder is replaced by the real designation as TWO schemes over
|
|
142
|
+
one gene database (`tests/data/typing/schemes/dec.json`, the typing/2 multi-scheme
|
|
143
|
+
showcase): `gb4789_6` (GB 4789.6-2016 panel semantics — EAEC is any-of aggR/pic/astA)
|
|
144
|
+
and `risk_monitoring` (最新食品安全风险监测方案 — aggR mandatory), both exact
|
|
145
|
+
semantics (cutoff 1.0, margin 0.0) with the `uidA` control gene, the `non-DEC` fallback,
|
|
146
|
+
and one severity-ordered rule ladder (EHEC > STEC/EPEC > ETEC > EIEC > EAEC; hybrids
|
|
147
|
+
surface as the runner_up; `EPEC_atypical` declared after EHEC/STEC so stx+ isolates never
|
|
148
|
+
land there). To encode it, `exact_set` rules gained an optional `requires_any` any-of
|
|
149
|
+
gate (satisfied iff all `requires` present AND, when the set is non-empty, at least one
|
|
150
|
+
`requires_any` present AND no `excludes` present; `requires` is now optional when
|
|
151
|
+
`requires_any` carries the constraint; the three sets must be pairwise disjoint and not
|
|
152
|
+
all empty — `TYPING_MALFORMED` otherwise; additive within typing/2, no schema bump).
|
|
153
|
+
The synthetic fixture `dec.fa` carries all 14 gene names plus duplicate pic/sth records
|
|
154
|
+
mirroring the rightsholder db (duplicate records collapse by gene name:
|
|
155
|
+
`-culling_limit 1` keeps the best subject, the engine folds one call per name). The
|
|
156
|
+
definitional matrix is locked end to end — including the headline divergence
|
|
157
|
+
(pic+astA+uidA → EAEC under gb4789_6, non-DEC under risk_monitoring, golden
|
|
158
|
+
`gene_dec_pic_astA`) — and hybrid severity ties (stx2a+escV+aggR → EHEC with EAEC at
|
|
159
|
+
1.0 as runner_up). No output-schema, TSV, or parity changes.
|
|
160
|
+
- **typing/2 cycle complete — the scheme cookbook (stage 3)**, consolidating the typing/2
|
|
161
|
+
story: stage 1 promoted the typing document to `gapit.typing/2` named multi-scheme
|
|
162
|
+
documents (a `/1` document degrades to one anonymous `default` scheme; gene-kind builds
|
|
163
|
+
gained `--typing`, one call per scheme — first keyed into gapit.report/1's phenotypes
|
|
164
|
+
object, later moved to the `gapit typing` command), stage 2 added the six rule/scheme
|
|
165
|
+
primitives (entry below), and stage 3 proves the framework encodes real designation
|
|
166
|
+
schemes: six researched schemes as validated example documents with synthetic marker
|
|
167
|
+
fixtures in `tests/data/typing/schemes/`, each self-checked end to end by the new
|
|
168
|
+
`test_typing_schemes*.py` suites (build fixture db → screen → asserted phenotype calls)
|
|
169
|
+
with goldens for one representative call per scheme (doumith 4b, shigella mixed, the
|
|
170
|
+
vp O:K compose, cholerae inaba). The cookbook: the complete Doumith Listeria table
|
|
171
|
+
(Doumith et al. 2004, incl. the 4b*/IVb-v1 HGT caveat falling back to NT), a
|
|
172
|
+
ShigaTyper-semantics Shigella/EIEC skeleton (Wu et al. 2019: ipaH_c control, wzx
|
|
173
|
+
unique-group mixed calls, sonnei form I/II with the exact-tie ordering, the lacY EIEC
|
|
174
|
+
approximation with the S. boydii 9/15 exemptions), the meningotype serogroup panel
|
|
175
|
+
(Mothershed et al. 2004 + the synG EX7E allele-probe trick at identity_floor 99.5),
|
|
176
|
+
the Vibrio parahaemolyticus O/K Kaptive pattern (van der Graaf-van Bloois et al. 2023:
|
|
177
|
+
cluster_match bands, the O3/O13 combined label, OUT/KUT fallbacks, per-scheme databases
|
|
178
|
+
— a cluster db carries exactly one scheme), V. cholerae O1/O139 + Ogawa/Inaba (wbeT
|
|
179
|
+
single-SNP allele floor, the negative-wbeT Inaba rule, Hikojima not determinable, the
|
|
180
|
+
wbfZ junction-gene trap note), and a documented DEC placeholder awaiting the
|
|
181
|
+
rightsholder's curated panel. New bilingual docs page `docs/typing.md` / `typing.zh.md`
|
|
182
|
+
(framework reference, primitive tables, the cookbook with citations, the allele
|
|
183
|
+
probe-trick section and its future allele_match successor, calibration pointer), wired
|
|
184
|
+
into mkdocs nav (EN + zh), the doc indexes, and the databases pages. No schema, output,
|
|
185
|
+
or TSV parity changes; parity 15/15 + summary 6/6 unchanged.
|
|
186
|
+
- typing/2 stage-2 rule primitives for declarative phenotype scoring (additive; existing
|
|
187
|
+
rule semantics, outputs, and goldens untouched): the `exact_set` rule (deterministic
|
|
188
|
+
boolean gene-set match with `requires`/`excludes` and 90/90-default identity/coverage
|
|
189
|
+
floors — a 1.0 tie involving a satisfied exact_set resolves by declaration order
|
|
190
|
+
instead of the ambiguity margin), optional `coverage_floor` on `weighted_genes` and
|
|
191
|
+
`exact_set`, scheme-level `control_gene` (absent control gene zeroes the scheme to its
|
|
192
|
+
fallback with a "control gene absent" note), scheme-level `unique_group` +
|
|
193
|
+
`mixed_phenotype` (multiple present group genes call the mixed phenotype with the pair
|
|
194
|
+
in `ambiguous`), `compose` schemes rendering `"{o_group}:{k_group}"` from sibling
|
|
195
|
+
schemes' calls (fallback strings flow through; an ambiguous ingredient yields a null
|
|
196
|
+
composition carrying that ingredient's variants), and rule-level `notes` surfaced
|
|
197
|
+
verbatim on winning phenotype calls. All new fields validate (`TYPING_MALFORMED`,
|
|
198
|
+
unknown gene references `TYPING_UNKNOWN_GENE`); rule models split into
|
|
199
|
+
`gapit.typing_rules` and the decision layer into `gapit.typing_decide` at the 250-LOC
|
|
200
|
+
ceiling.
|
|
201
|
+
- `gapit db list` renders a styled rich table (title "Databases"; cyan Provider, status-tinted
|
|
202
|
+
Status, yellow DBTYPE columns) when stdout is an interactive terminal. Piped or redirected
|
|
203
|
+
output keeps the byte-identical TSV, and `--json` is unchanged.
|
|
204
|
+
- Provider license metadata surfaced in `gapit db list --json` (`license` per provider when
|
|
205
|
+
pinned) and stamped into the build manifest (card, vfdb, ecoli_vf, kaptive).
|
|
206
|
+
- `vendor` field in `gapit.dblist/1` entries: the upstream maintainer organisation behind
|
|
207
|
+
every provider (NCBI, DTU CGE, Kaptive (klebgenomics), ...). Additive; `name` still
|
|
208
|
+
carries the database name passed to `--db`.
|
|
209
|
+
|
|
210
|
+
### Changed
|
|
211
|
+
|
|
212
|
+
- Uniform help-on-bare: commands that require input now print their full help when
|
|
213
|
+
invoked with no arguments at all — `gapit screen`, `summary`, `schema`, `db`,
|
|
214
|
+
`db fetch`, `db install`, `db build`, `db search` (typer `no_args_is_help`). The
|
|
215
|
+
help exits 2, the same code the bare root app has always used under click's
|
|
216
|
+
no-args-is-help semantics (recorded reality; the pre-change bare `screen`/`summary`
|
|
217
|
+
also exited 2, but with a `gapit.error/1` envelope instead of help, and bare
|
|
218
|
+
`schema`/`db install`/`db build`/`db search` raised click missing-argument errors).
|
|
219
|
+
Invocations with flags present but input missing keep their typed usage-error
|
|
220
|
+
envelopes (exit 2). Commands valid with no arguments (`mcp`, `setupdb`, `db list`,
|
|
221
|
+
`db outdated`) are unchanged. Breaking for `db fetch`: an omitted NAME no longer
|
|
222
|
+
installs the default set — the default-set download is now explicit
|
|
223
|
+
(`gapit db fetch all`, same DEFAULT_DBS order and receipts; bare fetch prints help,
|
|
224
|
+
and `db fetch --flags` without a NAME is a typed usage error), because a bare
|
|
225
|
+
invocation silently starting a multi-database download was a footgun. The MCP
|
|
226
|
+
`db_fetch` tool aligns: `name` is required and accepts the literal `all`. Docs
|
|
227
|
+
updated in step (EN + zh); no output schemas or goldens changed.
|
|
228
|
+
|
|
229
|
+
- Terminology sweep after the NAME/PROVIDER column split: user-facing text now reserves
|
|
230
|
+
PROVIDER for the upstream maintainer organisation and consistently calls the `--db`
|
|
231
|
+
value the database NAME. `gapit db fetch` help reads "Fetch and build database(s)"
|
|
232
|
+
with a "Database name" `[NAME]` argument help, `gapit db list` help reads "List known
|
|
233
|
+
databases (NAME, upstream PROVIDER) and their installed state", the `db` group help
|
|
234
|
+
says "database fetch" (was "provider fetch"), `db install` help says "no database
|
|
235
|
+
names" (was "no provider IDs"), and the MCP `db_fetch`/`db_list` tool descriptions use
|
|
236
|
+
database-name phrasing. The unknown-name error from `gapit db fetch` / the `db_fetch`
|
|
237
|
+
tool now reads `unknown database: NAME (available: ...)` with context key `db` (was
|
|
238
|
+
`unknown provider: ...` with context key `provider`); the error CODE stays `USAGE_ERROR`.
|
|
239
|
+
Docs updated in step (EN + zh). No flags, output schemas, exit codes, or internal
|
|
240
|
+
identifiers changed; the `gapit.dblist/1` `providers` array key is untouched.
|
|
241
|
+
|
|
242
|
+
- `gapit db list` TSV header is now `NAME PROVIDER STATUS DBTYPE DESCRIPTION`: the old
|
|
243
|
+
PROVIDER column actually held the database name users pass to `--db`, so it is renamed
|
|
244
|
+
NAME, and a new PROVIDER column names the upstream maintainer organisation (the `vendor`
|
|
245
|
+
above). Breaking for TSV consumers (header change, 4 → 5 columns); the rich table gained
|
|
246
|
+
the same NAME/PROVIDER split and `gapit.dblist/1` `name` is unchanged.
|
|
247
|
+
|
|
248
|
+
- card and vfdb unbundled to download-on-fetch providers (license compliance: their
|
|
249
|
+
non-commercial upstream terms — McMaster's for CARD, CC BY-NC for VFDB — are incompatible
|
|
250
|
+
with redistribution inside the MIT-licensed wheel). `ecoli_vf` pins its true license
|
|
251
|
+
(`CC BY-NC 4.0 (VFDB-derived content)` — the repo is labeled Apache but its README states
|
|
252
|
+
the content is taken from the VFDB). The bundled-snapshot archives, the snapshot-first
|
|
253
|
+
install path, the monthly snapshot-refresh CI workflow, and the `snapshot-update` /
|
|
254
|
+
`stale+snapshot-update` `db outdated` statuses are gone; `db outdated` now reports `ok`
|
|
255
|
+
or `stale` only.
|
|
256
|
+
- Kaptive cluster providers renamed/expanded to the seven official Kaptive v3 install
|
|
257
|
+
keywords — `kpsc_k`, `kpsc_o`, `kosc_k`, `kosc_o`, `ab_k`, `ab_o`, `ecoli_kps`
|
|
258
|
+
(K. pneumoniae species complex K/O, K. oxytoca species complex K/O, A. baumannii K/OC,
|
|
259
|
+
E. coli group 2+3 capsular polysaccharide loci) — each sourcing its raw GenBank file
|
|
260
|
+
from `main` of the actively curated per-species upstream repos
|
|
261
|
+
(klebgenomics.github.io/Kaptive/db/overview.html#available-databases), so fetches track
|
|
262
|
+
current curation instead of the frozen v2.0.9 archives the four old providers pinned.
|
|
263
|
+
Still GPL-3.0 download-on-fetch, never bundled; manifests record the new source URL,
|
|
264
|
+
license, and citation note (Kaptive/Wyres et al. 2020). The upstream `.toml`
|
|
265
|
+
identity-threshold metadata is not fetched in v1 (a future `typing.json` source).
|
|
266
|
+
|
|
267
|
+
### Removed
|
|
268
|
+
|
|
269
|
+
- `gapit db fetch --from-source` flag (meaningless now that no bundled snapshots exist:
|
|
270
|
+
every fetch downloads from upstream).
|
|
271
|
+
|
|
272
|
+
### Fixed
|
|
273
|
+
|
|
274
|
+
- **DEC panel provenance cleaning.** The original 17-record DEC panel carried two
|
|
275
|
+
VFDB-derived records (spotted past header inspection) plus VF-flavored metadata; all
|
|
276
|
+
records were re-sourced from NCBI/DDBJ primary submissions (100% same-allele, 5
|
|
277
|
+
replacements: bfpB, pic ×2, astA, stx2b, and the sth/stp/lt accessions re-verified),
|
|
278
|
+
and a regression test now mechanically asserts no `VF*` tags ride the bundled headers.
|
|
279
|
+
|
|
280
|
+
## [0.4.0] - 2026-09-30
|
|
281
|
+
|
|
282
|
+
### Added
|
|
283
|
+
|
|
284
|
+
- **Gene-cluster databases and cluster screening** (stages 1–3; the blastn gene path and
|
|
285
|
+
all existing outputs are untouched — parity stays byte-identical):
|
|
286
|
+
- `gapit db build NAME input.gbk|input.gff3` detects the input kind by suffix and builds
|
|
287
|
+
a `kind: cluster` database — locus FASTA `sequences`, `gapit.features/1` feature table
|
|
288
|
+
(`features.json`), makeblastdb index, manifest `kind: cluster` — with `--kind
|
|
289
|
+
gene|cluster` to override (usage error on contradiction). New parsers (no Biopython):
|
|
290
|
+
GenBank FEATURES/ORIGIN (Bakta/modern and kaptive-style source-note labels) and GFF3
|
|
291
|
+
(embedded `##FASTA` or sidecar); compound `join()` CDS locations are rejected with a
|
|
292
|
+
typed error.
|
|
293
|
+
- `gapit screen --db <cluster db>` dispatches to the minimap2 `asm20` cluster engine:
|
|
294
|
+
per-gene present/partial/absent verdicts (`--min-gene-cov`/`--min-gene-id`, default
|
|
295
|
+
90/90), cs-based union coverage/identity, cross-contig fragmentation resilience, and a
|
|
296
|
+
best-locus call above `--min-cluster-cov` (default 96). Output is the new
|
|
297
|
+
`gapit.cluster/1` document (json), the cluster TSV/CSV (one row per file), or
|
|
298
|
+
Markdown; kind-mismatched flags are usage errors; reads mode rejects cluster
|
|
299
|
+
databases. The MCP `screen` tool gains `minGeneCov`/`minGeneId`/`minClusterCov`.
|
|
300
|
+
- `--typing FILE` installs a validated `gapit.typing/1` declarative scoring spec into a
|
|
301
|
+
cluster db (`typing.json`). Screening a typed database annotates every best call with
|
|
302
|
+
a `phenotype` and an additive `phenotype_detail` breakdown (score, confidence,
|
|
303
|
+
per-rule components, runner-up, ambiguity pair); the TSV gains a PHENOTYPE column
|
|
304
|
+
(typed runs only — untyped output stays byte-identical). Three rule kinds —
|
|
305
|
+
`weighted_genes`, `cluster_match`, `learned_linear` (schema only; no training code) —
|
|
306
|
+
behind a `cutoff` + `ambiguity_margin` + `fallback` decision layer. Unknown gene/locus
|
|
307
|
+
references fail with `TYPING_UNKNOWN_GENE` at build AND screen time.
|
|
308
|
+
- Four kaptive cluster providers, `kaptive_k`, `kaptive_o`, `kaptive_ak`, `kaptive_oc`
|
|
309
|
+
(Klebsiella K/O and A. baumannii K/OC antigen loci; Wyres et al. 2020 — cite Kaptive).
|
|
310
|
+
The database content is GPL-3.0, so nothing is bundled: fetch downloads the pinned
|
|
311
|
+
Kaptive v2.0.9 GenBank files and builds cluster databases; manifests record the
|
|
312
|
+
source URL, `license`, and citation `note`. No typing model ships with them yet
|
|
313
|
+
(locus calls only, phenotype null).
|
|
314
|
+
- `scripts/cluster_calibration.py`: developer harness that screens a typed cluster db
|
|
315
|
+
against a labels TSV and prints the per-expected-phenotype score distribution, the
|
|
316
|
+
called×expected agreement matrix, and the divergence list (the v1 loop for future
|
|
317
|
+
learned_linear training).
|
|
318
|
+
- `gapit screen --merge-fragments` (blastn contig mode only; off by default): merge gene
|
|
319
|
+
fragments split across contig boundaries into one reported hit when their union subject
|
|
320
|
+
coverage reaches `--mincov`. Merged rows carry additive optional `merged` and `fragments`
|
|
321
|
+
fields in `gapit.report/1` JSON plus a Markdown detail line; the default path (and all
|
|
322
|
+
existing output) is untouched. The MCP `screen` tool gains the matching `mergeFragments`
|
|
323
|
+
boolean parameter.
|
|
324
|
+
|
|
325
|
+
## [0.3.1] - 2026-09-28
|
|
326
|
+
|
|
327
|
+
### Added
|
|
328
|
+
|
|
329
|
+
- `-h` now works as an alias for `--help` on every command (root, subcommands,
|
|
330
|
+
and nested `db` sub-app).
|
|
331
|
+
|
|
332
|
+
## [0.3.0] - 2026-09-28
|
|
333
|
+
|
|
334
|
+
### Removed
|
|
335
|
+
|
|
336
|
+
- `gapit list` command and the `gapit.list/1` schema (breaking; rightsholder decision to
|
|
337
|
+
drop abricate `--list` strict parity for this surface). `gapit db list` / `gapit.dblist/1`
|
|
338
|
+
is the single listing surface; `gapit schema` now introspects six documents.
|
|
339
|
+
|
|
340
|
+
## [0.2.2] - 2026-09-24
|
|
341
|
+
|
|
342
|
+
### Security
|
|
343
|
+
|
|
344
|
+
- minimap2 input paths are passed as absolute paths, so a file named like an option
|
|
345
|
+
(e.g. `-d`) can no longer inject minimap2 flags; the child process no longer inherits
|
|
346
|
+
stdin (the MCP protocol stream).
|
|
347
|
+
|
|
348
|
+
### Changed
|
|
349
|
+
|
|
350
|
+
- `--minid`/`--mincov` with `--aligner minimap2` or `--r1/--r2` are now a usage error
|
|
351
|
+
(exit 2) instead of being silently ignored.
|
|
352
|
+
- MCP `screen` (blastn) reuses the CLI use-case; its validation messages now match the CLI.
|
|
353
|
+
- MCP `screen_reads` passes read arrays natively, so filenames containing commas work.
|
|
354
|
+
|
|
355
|
+
### Fixed
|
|
356
|
+
|
|
357
|
+
- `gapit db list` now also lists databases installed into the datadir outside the provider
|
|
358
|
+
catalog: `db build` products (gene and cluster kinds) and manifest-less directories
|
|
359
|
+
(abricate-style or `db install` bytes) render after the registry entries, sorted by name,
|
|
360
|
+
with PROVIDER `local`, the record count from the manifest (FASTA count when absent), and
|
|
361
|
+
DBTYPE from the manifest / BLAST index suffix / letter heuristic. The gapit.dblist/1 JSON
|
|
362
|
+
gains them inside `providers` behind the additive `source: "local"` field — registry
|
|
363
|
+
entries simply lack the field, so pre-existing output is byte-identical; TSV, rich table,
|
|
364
|
+
and the MCP `db_list` tool share the same rows.
|
|
365
|
+
- MCP server replies `-32600`/`-32602` to malformed requests that carry an `id` instead of
|
|
366
|
+
silently dropping them.
|
|
367
|
+
- A truncated gzip reads file raises a typed `INVALID_READS_FORMAT` error (exit 5) instead
|
|
368
|
+
of `UNEXPECTED` (exit 1).
|
|
369
|
+
|
|
370
|
+
## [0.2.1] - 2026-09-22
|
|
371
|
+
|
|
372
|
+
### Changed
|
|
373
|
+
|
|
374
|
+
- License changed from GPL-2.0-only to MIT (rightsholder decision; behavioral
|
|
375
|
+
reimplementation status unchanged).
|
|
376
|
+
|
|
377
|
+
## [0.2.0] - 2026-09-22
|
|
378
|
+
|
|
379
|
+
Development window: 2026-09-15 to 2026-09-22 (PLAN.md Phases 1 through 8 and post-phase
|
|
380
|
+
hardening).
|
|
381
|
+
|
|
382
|
+
### Added
|
|
383
|
+
|
|
384
|
+
- Screening core: `any2fasta` to `blastn` pipeline with SPEC-exact hit processing, and
|
|
385
|
+
byte-compatible TSV against abricate 1.4.0 (PLAN Phases 1-3, 2026-09-15). Parity is
|
|
386
|
+
checked on a genome corpus with `pixi run -e parity parity` (6/6 byte-identical).
|
|
387
|
+
- Agent-facing outputs: `--format json|md` with versioned schemas (`gapit.report/1`,
|
|
388
|
+
`gapit.reads/1`, `gapit.summary/1`, `gapit.list/1`, `gapit.version/1`), the
|
|
389
|
+
`gapit.error/1` stderr envelope with documented exit codes, and introspection via
|
|
390
|
+
`gapit schema report|reads|summary|list|error|version` (2026-09-16).
|
|
391
|
+
- FASTQ reads mode via minimap2: `gapit screen --r1/--r2 --read-type sr|map-ont|map-hifi`;
|
|
392
|
+
presence is called on alignment breadth (2026-09-16).
|
|
393
|
+
- Summary matrix mode: `gapit summary` emits TSV/CSV/JSON/MD; byte parity with
|
|
394
|
+
`abricate --summary` via `pixi run -e parity summary-parity` (2026-09-17).
|
|
395
|
+
- `gapit db install`: checksum-verified (SHA256), atomic local-file installation
|
|
396
|
+
(2026-09-17).
|
|
397
|
+
- Native `gapit/v1` database format: tagged-header codec, `records.jsonl` truth store
|
|
398
|
+
with `gapit.manifest/1` provenance, deterministic build pipeline with self-check, and
|
|
399
|
+
`.mmi` BLAST index build with version-gated reuse (2026-09-18).
|
|
400
|
+
- 12 database providers (ncbi, card, resfinder, argannot, plasmidfinder, megares, ecoh,
|
|
401
|
+
vfdb, ecoli_vf, bacmet2, victors, upec_expec_vf) with offline-tested transforms
|
|
402
|
+
(2026-09-18).
|
|
403
|
+
- Bundled card and vfdb snapshots: a bare `gapit db fetch` installs the default set with
|
|
404
|
+
zero network; `--from-source` forces upstream download (2026-09-18).
|
|
405
|
+
- CLI hardening: shell completions, `--debug` argv echo on stderr, and `--jobs` parallel
|
|
406
|
+
screening across inputs with input-order stdout (2026-09-18).
|
|
407
|
+
- CI: gates matrix (lint, fmt, typecheck, test on Python 3.11 / 3.13 / 3.14) plus a
|
|
408
|
+
parity job that byte-diffs against real abricate (2026-09-18).
|
|
409
|
+
- MCP stdio server: `gapit mcp` subcommand and `gapit-mcp` console script, hand-rolled
|
|
410
|
+
JSON-RPC 2.0 with zero new dependencies; read-only tools `screen`, `summary`,
|
|
411
|
+
`schema`, `db_list` (2026-09-18).
|
|
412
|
+
- Conda recipe (`recipe/meta.yaml`) for PyPI/bioconda packaging (2026-09-18).
|
|
413
|
+
- Custom database construction: `gapit db build NAME FASTA` builds a screening-ready native
|
|
414
|
+
database from plain, abricate `~~~`, or `gapit|` FASTA (auto-detected), with optional
|
|
415
|
+
`--tsv` metadata (accession, function classes) and `--dbtype` override; guide with worked
|
|
416
|
+
examples in `docs/custom-db.md` (2026-09-19).
|
|
417
|
+
- `--aligner blastn|minimap2` engine selector on `gapit screen`: defaults follow the input
|
|
418
|
+
(blastn for contig files, minimap2 for `--r1`/`--r2` reads); `--aligner minimap2` screens
|
|
419
|
+
positional assembly FASTA through the minimap2 engine, `--aligner blastn` with `--r1`/`--r2`
|
|
420
|
+
is a usage error (2026-09-19).
|
|
421
|
+
- `gapit db outdated`: staleness report over installed databases (age vs `--days`, newer
|
|
422
|
+
bundled snapshot) as a TSV table or `gapit.dboutdated/1` JSON document (2026-09-20).
|
|
423
|
+
- `gapit db search TERM`: case-insensitive gene/accession/function/product lookup across
|
|
424
|
+
installed databases' `records.jsonl`, with `--field`, `--exact`, `--db`, `--limit` and
|
|
425
|
+
JSONL output (2026-09-20).
|
|
426
|
+
- MCP database tools `db_fetch`, `db_build`, `db_search`, `db_outdated`: the MCP server now
|
|
427
|
+
exposes the `db` commands alongside the analysis tools, so agents can self-provision and
|
|
428
|
+
inspect databases mid-session; `mcp.py` split into protocol (`mcp.py`) and tool
|
|
429
|
+
implementations (`mcp_tools.py`) with zero wire change for the existing tools (2026-09-20).
|
|
430
|
+
- CI snapshot refresh: monthly scheduled workflow (`.github/workflows/snapshot-refresh.yml`)
|
|
431
|
+
re-fetching card and vfdb from upstream, regenerating the bundled tars only when the
|
|
432
|
+
records changed, and opening a review PR (2026-09-20).
|
|
433
|
+
- Reads-mode opt-in alignment filtering: `gapit screen --min-identity/--min-mapq` (reads
|
|
434
|
+
engine only) drops PAF alignments below the thresholds before aggregation and emits the new
|
|
435
|
+
`gapit.reads/2` document (params gain both thresholds; gene entries gain
|
|
436
|
+
`mean_identity_pct`, the alignment-length-weighted mean identity; introspectable via
|
|
437
|
+
`gapit schema reads2`). Both flags off keeps `gapit.reads/1` byte-identical, and the
|
|
438
|
+
identity floor fixes the documented family-splitting over-calls on homologous genes
|
|
439
|
+
(2026-09-20).
|
|
440
|
+
- MCP reads tools: new `screen_reads` tool (FASTQ lanes via minimap2 → `gapit.reads/1`,
|
|
441
|
+
`min_identity`/`min_mapq` > 0 → `gapit.reads/2`) and new `screen` arguments
|
|
442
|
+
`aligner`/`min_breadth`/`min_identity`/`min_mapq` (`aligner minimap2` = fast assembly
|
|
443
|
+
survey). Both delegate to the shared reads use-cases with `quiet` stderr; additive
|
|
444
|
+
`gapit.mcp` contract — nine tools, the other eight wire-identical, no output-schema
|
|
445
|
+
version bump (2026-09-22).
|
|
446
|
+
|
|
447
|
+
### Changed
|
|
448
|
+
|
|
449
|
+
- `any2fasta` is no longer a runtime dependency: input normalization (FASTA/FASTQ/GenBank/EMBL,
|
|
450
|
+
plain/gz/bz2 → FASTA) is native (`seqconvert.py`, perl-extracted semantics) and blastn reads the
|
|
451
|
+
converted FASTA on stdin. Parsed-record equivalence with the binary is differentially tested
|
|
452
|
+
with the parity env on PATH (abricate provides any2fasta transitively), and `.fa` parity
|
|
453
|
+
remains byte-identical (2026-09-21).
|
|
454
|
+
- Screening and reads paths route `gapit/v1` tagged headers to the native codec; legacy
|
|
455
|
+
abricate `~~~` headers keep the frozen parser, so abricate-built datadirs screen
|
|
456
|
+
identically. The reverse does not hold: gapit-built databases are unreadable by
|
|
457
|
+
abricate (accepted trade-off).
|
|
458
|
+
- A bare `gapit db fetch` installs the bundled default set (card, vfdb) instead of
|
|
459
|
+
downloading; `--from-source` restores the upstream fetch path.
|
|
460
|
+
- `gapit setupdb` honors the `gapit.manifest/1` dbtype on reindex (manifest-less abricate
|
|
461
|
+
dirs keep the mol_type heuristic), and reads/minimap2-assembly screening now rejects the
|
|
462
|
+
blastn-only flags `--fofn`, `--noheader`, `--nopath`, `--jobs N>1` with usage errors
|
|
463
|
+
(exit 2) instead of silently ignoring them (2026-09-22).
|
|
464
|
+
|
|
465
|
+
### Removed
|
|
466
|
+
|
|
467
|
+
- `--csv` flag on `gapit screen`; use `--format csv` instead (breaking: the flag is now
|
|
468
|
+
rejected as an unknown option, exit 2) (2026-09-19).
|
|
469
|
+
|
|
470
|
+
### Fixed
|
|
471
|
+
|
|
472
|
+
- Summary mode auto-detects TSV vs CSV per input file, avoiding the upstream quirk where
|
|
473
|
+
a global `--csv` flag mangles mixed-format input sets.
|