gea-program 0.30.1__tar.gz → 0.31.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (280) hide show
  1. {gea_program-0.30.1/gea_program.egg-info → gea_program-0.31.0}/PKG-INFO +22 -4
  2. {gea_program-0.30.1 → gea_program-0.31.0}/README.md +21 -3
  3. {gea_program-0.30.1 → gea_program-0.31.0}/gea/__init__.py +1 -1
  4. {gea_program-0.30.1 → gea_program-0.31.0}/gea/__main__.py +76 -0
  5. {gea_program-0.30.1 → gea_program-0.31.0}/gea/acceptance_tests.py +150 -0
  6. gea_program-0.31.0/gea/help/tools.md +11 -0
  7. {gea_program-0.30.1 → gea_program-0.31.0}/gea/helplib.py +1 -1
  8. gea_program-0.31.0/gea/reference/tool_sources.json +3046 -0
  9. {gea_program-0.30.1 → gea_program-0.31.0}/gea/service.py +31 -0
  10. gea_program-0.31.0/gea/tool_taxonomy.py +905 -0
  11. {gea_program-0.30.1 → gea_program-0.31.0}/gea/web/app.html +99 -2
  12. {gea_program-0.30.1 → gea_program-0.31.0/gea_program.egg-info}/PKG-INFO +22 -4
  13. {gea_program-0.30.1 → gea_program-0.31.0}/gea_program.egg-info/SOURCES.txt +2 -0
  14. {gea_program-0.30.1 → gea_program-0.31.0}/pyproject.toml +1 -1
  15. gea_program-0.30.1/gea/help/tools.md +0 -11
  16. {gea_program-0.30.1 → gea_program-0.31.0}/LICENSE +0 -0
  17. {gea_program-0.30.1 → gea_program-0.31.0}/gea/BENCH_TEST_PROTOCOL.md +0 -0
  18. {gea_program-0.30.1 → gea_program-0.31.0}/gea/accuracy_statement.py +0 -0
  19. {gea_program-0.30.1 → gea_program-0.31.0}/gea/alarm_engine.py +0 -0
  20. {gea_program-0.30.1 → gea_program-0.31.0}/gea/backup.py +0 -0
  21. {gea_program-0.30.1 → gea_program-0.31.0}/gea/bench.py +0 -0
  22. {gea_program-0.30.1 → gea_program-0.31.0}/gea/blind_harness.py +0 -0
  23. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/acex_lomonosov_age_depth_model.provenance.json +0 -0
  24. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/acex_lomonosov_age_depth_model.txt +0 -0
  25. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/agassiz77_canada_temperature.csv +0 -0
  26. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/agassiz77_canada_temperature.provenance.json +0 -0
  27. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/barbados_110_consolidation.provenance.json +0 -0
  28. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/barbados_110_consolidation.txt +0 -0
  29. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/bengal_u1452_grain_size.provenance.json +0 -0
  30. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/bengal_u1452_grain_size.txt +0 -0
  31. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/blake_164_methane_isotopes.provenance.json +0 -0
  32. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/blake_164_methane_isotopes.txt +0 -0
  33. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.provenance.json +0 -0
  34. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.txt +0 -0
  35. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/collingwood_1_28_ks_complete.las +0 -0
  36. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/collingwood_1_28_ks_complete.provenance.json +0 -0
  37. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/costa_rica_odp_friction_envelope.provenance.json +0 -0
  38. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/costa_rica_odp_friction_envelope.txt +0 -0
  39. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.provenance.json +0 -0
  40. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.txt +0 -0
  41. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/dsdp_504b_physical_properties.provenance.json +0 -0
  42. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/dsdp_504b_physical_properties.txt +0 -0
  43. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/dsdp_504b_sound_velocity.provenance.json +0 -0
  44. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/dsdp_504b_sound_velocity.txt +0 -0
  45. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/elgygytgyn_5011_turbidites.provenance.json +0 -0
  46. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/elgygytgyn_5011_turbidites.txt +0 -0
  47. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/epica_domec_co2_800kyr.provenance.json +0 -0
  48. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/epica_domec_co2_800kyr.txt +0 -0
  49. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/fram_909_organic_petrography.provenance.json +0 -0
  50. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/fram_909_organic_petrography.txt +0 -0
  51. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/gbr_325_coral_uth_ages.provenance.json +0 -0
  52. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/gbr_325_coral_uth_ages.txt +0 -0
  53. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/gisp2_greenland_temperature.csv +0 -0
  54. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/gisp2_greenland_temperature.provenance.json +0 -0
  55. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/gom_308_t2p_insitu.provenance.json +0 -0
  56. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/gom_308_t2p_insitu.txt +0 -0
  57. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/guaymas_385_dom_d13c.provenance.json +0 -0
  58. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/guaymas_385_dom_d13c.txt +0 -0
  59. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/hikurangi_u1520_friction_insitu.provenance.json +0 -0
  60. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/hikurangi_u1520_friction_insitu.txt +0 -0
  61. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.provenance.json +0 -0
  62. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.txt +0 -0
  63. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/iodp_u1324_pore_pressure.provenance.json +0 -0
  64. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/iodp_u1324_pore_pressure.txt +0 -0
  65. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/jfast_c0019_slow_slip_events.provenance.json +0 -0
  66. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/jfast_c0019_slow_slip_events.txt +0 -0
  67. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/kennetcook_2_p129_excerpt.las +0 -0
  68. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/kennetcook_2_p129_excerpt.provenance.json +0 -0
  69. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/ktb_hb_bhgm_density.dat +0 -0
  70. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/ktb_hb_bhgm_density.provenance.json +0 -0
  71. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/ktb_hb_complog_6020_excerpt.provenance.json +0 -0
  72. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/ktb_hb_complog_6020_excerpt.txt +0 -0
  73. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/ktb_hb_hlog246_temperature.dat +0 -0
  74. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/ktb_hb_hlog246_temperature.provenance.json +0 -0
  75. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/ktb_hb_rockmech_compress.dat +0 -0
  76. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/ktb_hb_rockmech_compress.provenance.json +0 -0
  77. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.dat +0 -0
  78. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.provenance.json +0 -0
  79. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/ktb_vb_rockmech_compress.dat +0 -0
  80. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/ktb_vb_rockmech_compress.provenance.json +0 -0
  81. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/ktb_vb_vlog251_temperature.dat +0 -0
  82. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/ktb_vb_vlog251_temperature.provenance.json +0 -0
  83. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/l06_06_nl_survey.csv +0 -0
  84. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/l06_06_nl_survey.provenance.json +0 -0
  85. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/l07_01_nl_excerpt.las +0 -0
  86. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/l07_01_nl_excerpt.provenance.json +0 -0
  87. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/mariana_1200_serpentinite_geochem.provenance.json +0 -0
  88. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/mariana_1200_serpentinite_geochem.txt +0 -0
  89. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/med_160_sapropels.provenance.json +0 -0
  90. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/med_160_sapropels.txt +0 -0
  91. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/nankai_megasplay_shear_strength.provenance.json +0 -0
  92. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/nankai_megasplay_shear_strength.txt +0 -0
  93. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/odp_1027b_thermal_conductivity.provenance.json +0 -0
  94. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/odp_1027b_thermal_conductivity.txt +0 -0
  95. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/odp_1027c_cork_temperature.provenance.json +0 -0
  96. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/odp_1027c_cork_temperature.txt +0 -0
  97. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/odp_1165b_thermal_conductivity.provenance.json +0 -0
  98. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/odp_1165b_thermal_conductivity.txt +0 -0
  99. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.provenance.json +0 -0
  100. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.txt +0 -0
  101. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/odp_504b_dike_elastic_moduli.provenance.json +0 -0
  102. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/odp_504b_dike_elastic_moduli.txt +0 -0
  103. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/odp_504b_leg137_borehole_fluids.provenance.json +0 -0
  104. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/odp_504b_leg137_borehole_fluids.txt +0 -0
  105. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.provenance.json +0 -0
  106. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.txt +0 -0
  107. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/peru_201_sulfate_reduction.provenance.json +0 -0
  108. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/peru_201_sulfate_reduction.txt +0 -0
  109. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/scorpio_e1_sa_excerpt.las +0 -0
  110. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/scorpio_e1_sa_excerpt.provenance.json +0 -0
  111. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/sumatra_362_cohesion.provenance.json +0 -0
  112. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/sumatra_362_cohesion.txt +0 -0
  113. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/university_6_17_no1_tx_excerpt.las +0 -0
  114. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/university_6_17_no1_tx_excerpt.provenance.json +0 -0
  115. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/ursa_308_xrd_mineralogy.provenance.json +0 -0
  116. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/ursa_308_xrd_mineralogy.txt +0 -0
  117. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/volve_15_9_19_sr_excerpt.las +0 -0
  118. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/volve_15_9_19_sr_excerpt.provenance.json +0 -0
  119. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/volve_15_9_19a_core_excerpt.csv +0 -0
  120. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/volve_15_9_19a_core_excerpt.provenance.json +0 -0
  121. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/volve_f12_f14_production_excerpt.csv +0 -0
  122. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/volve_f12_f14_production_excerpt.provenance.json +0 -0
  123. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/walvis_208_petm_carbonate.provenance.json +0 -0
  124. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/walvis_208_petm_carbonate.txt +0 -0
  125. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/woodlark_1109_rock_eval.provenance.json +0 -0
  126. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog/woodlark_1109_rock_eval.txt +0 -0
  127. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog_map.py +0 -0
  128. {gea_program-0.30.1 → gea_program-0.31.0}/gea/catalog_register.py +0 -0
  129. {gea_program-0.30.1 → gea_program-0.31.0}/gea/certificates.py +0 -0
  130. {gea_program-0.30.1 → gea_program-0.31.0}/gea/cli.py +0 -0
  131. {gea_program-0.30.1 → gea_program-0.31.0}/gea/client_reports.py +0 -0
  132. {gea_program-0.30.1 → gea_program-0.31.0}/gea/config_versioning.py +0 -0
  133. {gea_program-0.30.1 → gea_program-0.31.0}/gea/conformance.py +0 -0
  134. {gea_program-0.30.1 → gea_program-0.31.0}/gea/correlation.py +0 -0
  135. {gea_program-0.30.1 → gea_program-0.31.0}/gea/dashboard.py +0 -0
  136. {gea_program-0.30.1 → gea_program-0.31.0}/gea/deviation.py +0 -0
  137. {gea_program-0.30.1 → gea_program-0.31.0}/gea/dlis.py +0 -0
  138. {gea_program-0.30.1 → gea_program-0.31.0}/gea/dnp3.py +0 -0
  139. {gea_program-0.30.1 → gea_program-0.31.0}/gea/doctor.py +0 -0
  140. {gea_program-0.30.1 → gea_program-0.31.0}/gea/downhole_engine.py +0 -0
  141. {gea_program-0.30.1 → gea_program-0.31.0}/gea/drift_monitor.py +0 -0
  142. {gea_program-0.30.1 → gea_program-0.31.0}/gea/earth_model.py +0 -0
  143. {gea_program-0.30.1 → gea_program-0.31.0}/gea/edr.py +0 -0
  144. {gea_program-0.30.1 → gea_program-0.31.0}/gea/elevation.py +0 -0
  145. {gea_program-0.30.1 → gea_program-0.31.0}/gea/etp.py +0 -0
  146. {gea_program-0.30.1 → gea_program-0.31.0}/gea/etp12_schemas.json +0 -0
  147. {gea_program-0.30.1 → gea_program-0.31.0}/gea/example_register_map.json +0 -0
  148. {gea_program-0.30.1 → gea_program-0.31.0}/gea/fat_sat.py +0 -0
  149. {gea_program-0.30.1 → gea_program-0.31.0}/gea/files.py +0 -0
  150. {gea_program-0.30.1 → gea_program-0.31.0}/gea/fixtures/README.md +0 -0
  151. {gea_program-0.30.1 → gea_program-0.31.0}/gea/fixtures/comcat_delaware_basin_2026-09.txt +0 -0
  152. {gea_program-0.30.1 → gea_program-0.31.0}/gea/fixtures/comcat_youngstown_2011-2012.txt +0 -0
  153. {gea_program-0.30.1 → gea_program-0.31.0}/gea/fixtures/ne_110m_coastline.json +0 -0
  154. {gea_program-0.30.1 → gea_program-0.31.0}/gea/follower.py +0 -0
  155. {gea_program-0.30.1 → gea_program-0.31.0}/gea/forward_model.py +0 -0
  156. {gea_program-0.30.1 → gea_program-0.31.0}/gea/friction_priors.py +0 -0
  157. {gea_program-0.30.1 → gea_program-0.31.0}/gea/gamma.py +0 -0
  158. {gea_program-0.30.1 → gea_program-0.31.0}/gea/gauge_aging.py +0 -0
  159. {gea_program-0.30.1 → gea_program-0.31.0}/gea/gauge_specs.py +0 -0
  160. {gea_program-0.30.1 → gea_program-0.31.0}/gea/geodesy.py +0 -0
  161. {gea_program-0.30.1 → gea_program-0.31.0}/gea/gravity_reference.py +0 -0
  162. {gea_program-0.30.1 → gea_program-0.31.0}/gea/hartip.py +0 -0
  163. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/TESTER_GUIDE.md +0 -0
  164. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/alarms.md +0 -0
  165. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/audit-update.md +0 -0
  166. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/backup.md +0 -0
  167. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/catalog.md +0 -0
  168. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/conformance.md +0 -0
  169. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/data-in.md +0 -0
  170. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/dlis.md +0 -0
  171. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/doctor.md +0 -0
  172. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/drift.md +0 -0
  173. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/edr.md +0 -0
  174. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/etp.md +0 -0
  175. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/field-ports.md +0 -0
  176. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/files.md +0 -0
  177. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/historian.md +0 -0
  178. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/instruments.md +0 -0
  179. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/interval.md +0 -0
  180. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/month-end.md +0 -0
  181. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/notifications.md +0 -0
  182. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/osdu.md +0 -0
  183. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/patches.md +0 -0
  184. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/ppdm.md +0 -0
  185. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/quakeml.md +0 -0
  186. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/quality.md +0 -0
  187. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/seedlink.md +0 -0
  188. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/seismic.md +0 -0
  189. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/site.md +0 -0
  190. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/sites.md +0 -0
  191. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/slip.md +0 -0
  192. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/soak.md +0 -0
  193. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/sra.md +0 -0
  194. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/start.md +0 -0
  195. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/structure.md +0 -0
  196. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/transients.md +0 -0
  197. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/upkeep.md +0 -0
  198. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/vibration.md +0 -0
  199. {gea_program-0.30.1 → gea_program-0.31.0}/gea/help/well-tests.md +0 -0
  200. {gea_program-0.30.1 → gea_program-0.31.0}/gea/housekeeping.py +0 -0
  201. {gea_program-0.30.1 → gea_program-0.31.0}/gea/interval.py +0 -0
  202. {gea_program-0.30.1 → gea_program-0.31.0}/gea/inverse_engine.py +0 -0
  203. {gea_program-0.30.1 → gea_program-0.31.0}/gea/jobs.py +0 -0
  204. {gea_program-0.30.1 → gea_program-0.31.0}/gea/live_ports.py +0 -0
  205. {gea_program-0.30.1 → gea_program-0.31.0}/gea/loadtest.py +0 -0
  206. {gea_program-0.30.1 → gea_program-0.31.0}/gea/matplotlib_demo.py +0 -0
  207. {gea_program-0.30.1 → gea_program-0.31.0}/gea/modbus.py +0 -0
  208. {gea_program-0.30.1 → gea_program-0.31.0}/gea/modbus_rtu.py +0 -0
  209. {gea_program-0.30.1 → gea_program-0.31.0}/gea/model_card.py +0 -0
  210. {gea_program-0.30.1 → gea_program-0.31.0}/gea/month_end.py +0 -0
  211. {gea_program-0.30.1 → gea_program-0.31.0}/gea/mqtt_port.py +0 -0
  212. {gea_program-0.30.1 → gea_program-0.31.0}/gea/notify.py +0 -0
  213. {gea_program-0.30.1 → gea_program-0.31.0}/gea/opcua_port.py +0 -0
  214. {gea_program-0.30.1 → gea_program-0.31.0}/gea/operator_app.py +0 -0
  215. {gea_program-0.30.1 → gea_program-0.31.0}/gea/osdu.py +0 -0
  216. {gea_program-0.30.1 → gea_program-0.31.0}/gea/patches.py +0 -0
  217. {gea_program-0.30.1 → gea_program-0.31.0}/gea/permits.py +0 -0
  218. {gea_program-0.30.1 → gea_program-0.31.0}/gea/piwebapi.py +0 -0
  219. {gea_program-0.30.1 → gea_program-0.31.0}/gea/ports.py +0 -0
  220. {gea_program-0.30.1 → gea_program-0.31.0}/gea/ppdm.py +0 -0
  221. {gea_program-0.30.1 → gea_program-0.31.0}/gea/profile_catalog.py +0 -0
  222. {gea_program-0.30.1 → gea_program-0.31.0}/gea/project.py +0 -0
  223. {gea_program-0.30.1 → gea_program-0.31.0}/gea/qt6_downhole_app.py +0 -0
  224. {gea_program-0.30.1 → gea_program-0.31.0}/gea/quakeml.py +0 -0
  225. {gea_program-0.30.1 → gea_program-0.31.0}/gea/reconciler.py +0 -0
  226. {gea_program-0.30.1 → gea_program-0.31.0}/gea/reference/IU_ANMO_10_BHZ_response.provenance.json +0 -0
  227. {gea_program-0.30.1 → gea_program-0.31.0}/gea/reference/IU_ANMO_10_BHZ_response.xml +0 -0
  228. {gea_program-0.30.1 → gea_program-0.31.0}/gea/reference/libmseed_steim.provenance.json +0 -0
  229. {gea_program-0.30.1 → gea_program-0.31.0}/gea/reference/libmseed_steim1_4096.mseed +0 -0
  230. {gea_program-0.30.1 → gea_program-0.31.0}/gea/reference/libmseed_steim2_4096.mseed +0 -0
  231. {gea_program-0.30.1 → gea_program-0.31.0}/gea/reference/libmseed_steim2_512.mseed +0 -0
  232. {gea_program-0.30.1 → gea_program-0.31.0}/gea/rock_inventory.py +0 -0
  233. {gea_program-0.30.1 → gea_program-0.31.0}/gea/sample_record.py +0 -0
  234. {gea_program-0.30.1 → gea_program-0.31.0}/gea/sample_well_profile.csv +0 -0
  235. {gea_program-0.30.1 → gea_program-0.31.0}/gea/sbom.py +0 -0
  236. {gea_program-0.30.1 → gea_program-0.31.0}/gea/seedlink.py +0 -0
  237. {gea_program-0.30.1 → gea_program-0.31.0}/gea/segy.py +0 -0
  238. {gea_program-0.30.1 → gea_program-0.31.0}/gea/seismic.py +0 -0
  239. {gea_program-0.30.1 → gea_program-0.31.0}/gea/seismic_array.py +0 -0
  240. {gea_program-0.30.1 → gea_program-0.31.0}/gea/seismic_assoc.py +0 -0
  241. {gea_program-0.30.1 → gea_program-0.31.0}/gea/seismic_detect.py +0 -0
  242. {gea_program-0.30.1 → gea_program-0.31.0}/gea/seismic_film.py +0 -0
  243. {gea_program-0.30.1 → gea_program-0.31.0}/gea/seismic_harmonic.py +0 -0
  244. {gea_program-0.30.1 → gea_program-0.31.0}/gea/seismic_qc.py +0 -0
  245. {gea_program-0.30.1 → gea_program-0.31.0}/gea/seismic_response.py +0 -0
  246. {gea_program-0.30.1 → gea_program-0.31.0}/gea/seismic_signature.py +0 -0
  247. {gea_program-0.30.1 → gea_program-0.31.0}/gea/seismic_track.py +0 -0
  248. {gea_program-0.30.1 → gea_program-0.31.0}/gea/seismic_uncertainty.py +0 -0
  249. {gea_program-0.30.1 → gea_program-0.31.0}/gea/seismic_unlisted.py +0 -0
  250. {gea_program-0.30.1 → gea_program-0.31.0}/gea/sensor_swap.py +0 -0
  251. {gea_program-0.30.1 → gea_program-0.31.0}/gea/service_life.py +0 -0
  252. {gea_program-0.30.1 → gea_program-0.31.0}/gea/shapefile.py +0 -0
  253. {gea_program-0.30.1 → gea_program-0.31.0}/gea/shell.py +0 -0
  254. {gea_program-0.30.1 → gea_program-0.31.0}/gea/shut_in.py +0 -0
  255. {gea_program-0.30.1 → gea_program-0.31.0}/gea/sla_report.py +0 -0
  256. {gea_program-0.30.1 → gea_program-0.31.0}/gea/slip.py +0 -0
  257. {gea_program-0.30.1 → gea_program-0.31.0}/gea/soak.py +0 -0
  258. {gea_program-0.30.1 → gea_program-0.31.0}/gea/sra.py +0 -0
  259. {gea_program-0.30.1 → gea_program-0.31.0}/gea/store_forward.py +0 -0
  260. {gea_program-0.30.1 → gea_program-0.31.0}/gea/strata_join.py +0 -0
  261. {gea_program-0.30.1 → gea_program-0.31.0}/gea/structure.py +0 -0
  262. {gea_program-0.30.1 → gea_program-0.31.0}/gea/supervisor.py +0 -0
  263. {gea_program-0.30.1 → gea_program-0.31.0}/gea/survey_cmd.py +0 -0
  264. {gea_program-0.30.1 → gea_program-0.31.0}/gea/survey_view.py +0 -0
  265. {gea_program-0.30.1 → gea_program-0.31.0}/gea/telemetry.py +0 -0
  266. {gea_program-0.30.1 → gea_program-0.31.0}/gea/tool_catalog.py +0 -0
  267. {gea_program-0.30.1 → gea_program-0.31.0}/gea/tool_library.py +0 -0
  268. {gea_program-0.30.1 → gea_program-0.31.0}/gea/transient.py +0 -0
  269. {gea_program-0.30.1 → gea_program-0.31.0}/gea/vibration.py +0 -0
  270. {gea_program-0.30.1 → gea_program-0.31.0}/gea/well_assembler.py +0 -0
  271. {gea_program-0.30.1 → gea_program-0.31.0}/gea/well_test_validation.py +0 -0
  272. {gea_program-0.30.1 → gea_program-0.31.0}/gea/wits0.py +0 -0
  273. {gea_program-0.30.1 → gea_program-0.31.0}/gea/witsml.py +0 -0
  274. {gea_program-0.30.1 → gea_program-0.31.0}/gea/workspace.py +0 -0
  275. {gea_program-0.30.1 → gea_program-0.31.0}/gea_program.egg-info/dependency_links.txt +0 -0
  276. {gea_program-0.30.1 → gea_program-0.31.0}/gea_program.egg-info/entry_points.txt +0 -0
  277. {gea_program-0.30.1 → gea_program-0.31.0}/gea_program.egg-info/requires.txt +0 -0
  278. {gea_program-0.30.1 → gea_program-0.31.0}/gea_program.egg-info/top_level.txt +0 -0
  279. {gea_program-0.30.1 → gea_program-0.31.0}/setup.cfg +0 -0
  280. {gea_program-0.30.1 → gea_program-0.31.0}/tests/test_acceptance.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gea-program
3
- Version: 0.30.1
3
+ Version: 0.31.0
4
4
  Summary: GEA-Program: downhole gauge monitoring - canonical measurement records, quality rules, drift evaluation with a re-fit change log, well-test validation, alarm management, model cards, store-and-forward, monthly SLA measurement, FAT/SAT protocols and a dashboard, generated from live objects in the client's reporting outline.
5
5
  Author: Daniel T. Murphy
6
6
  License: MPL-2.0
@@ -125,7 +125,7 @@ gea dashboard --catalog-well volve_f12_f14_production_excerpt:15/9-F-12:10000 --
125
125
  gea client-report --report accuracy --out client_report
126
126
  gea model-cards --out model_cards
127
127
  gea sbom --out sbom
128
- gea accept # the product gate (377 checks)
128
+ gea accept # the product gate (380 checks)
129
129
  gea help drift # the help library, by the job (16 pages; the same text is on every dashboard page)
130
130
  gea guide # the click-by-click tester guide (docs/TESTER_GUIDE.md)
131
131
  gea gui # the desktop window (pip install "gea-program[desktop]")
@@ -650,8 +650,26 @@ itself; `gea help seedlink`. A TexNet station is served by EarthScope at
650
650
 
651
651
  ### Tools and ports
652
652
 
653
- The Tools & ports tab (`#/tools`, `gea tools`) is the program's two
654
- registers in one place: the tool library - every downhole and surface tool
653
+ The Tools & ports tab (`#/tools`, `gea tools`) opens on the **downhole tool
654
+ library**: every class of downhole tool in use across the industry - bits
655
+ and hole openers, motors and rotary steerable systems, MWD and LWD, the drill
656
+ string and its subs, casing and cementing equipment, completion and
657
+ artificial lift, wireline and cased-hole tools, fishing and milling, test
658
+ tools - ninety-six classes in nine categories. Point at a tool, or Tab to
659
+ it, for a one-line description; click, tap or press Enter for its tutorial:
660
+ what it is, where it runs, how it works, what it shows in the data, what to
661
+ watch, and what this program does with it, with the published figures
662
+ quoted from the pages they cite and the pages themselves. The tutorials
663
+ carry no numbers of their own; a figure on a tool's card is the cited page's
664
+ words, most often one maker's product, never a limit for the class. Your
665
+ **fleet** - the tools you actually run - goes in beside the classes, each
666
+ with its maker, model, serial and the datasheet that rates it
667
+ (`gea tools --action fleet-add --workspace C:\site --class pdm_motor
668
+ --maker ... --model ... --datasheet ...`, or from the tutorial), kept in the
669
+ workspace and audited. `gea tools --action classes`, `--action tutorial
670
+ --class drilling_jar`.
671
+
672
+ Below it are the program's two registers: the gauge library - every gauge
655
673
  with its source citation, ratings, what it measures, the telemetry interface
656
674
  it declares and its datasheet aging rate where the vendor published one -
657
675
  and the ports, the file formats read and the eleven live protocols spoken,
@@ -86,7 +86,7 @@ gea dashboard --catalog-well volve_f12_f14_production_excerpt:15/9-F-12:10000 --
86
86
  gea client-report --report accuracy --out client_report
87
87
  gea model-cards --out model_cards
88
88
  gea sbom --out sbom
89
- gea accept # the product gate (377 checks)
89
+ gea accept # the product gate (380 checks)
90
90
  gea help drift # the help library, by the job (16 pages; the same text is on every dashboard page)
91
91
  gea guide # the click-by-click tester guide (docs/TESTER_GUIDE.md)
92
92
  gea gui # the desktop window (pip install "gea-program[desktop]")
@@ -611,8 +611,26 @@ itself; `gea help seedlink`. A TexNet station is served by EarthScope at
611
611
 
612
612
  ### Tools and ports
613
613
 
614
- The Tools & ports tab (`#/tools`, `gea tools`) is the program's two
615
- registers in one place: the tool library - every downhole and surface tool
614
+ The Tools & ports tab (`#/tools`, `gea tools`) opens on the **downhole tool
615
+ library**: every class of downhole tool in use across the industry - bits
616
+ and hole openers, motors and rotary steerable systems, MWD and LWD, the drill
617
+ string and its subs, casing and cementing equipment, completion and
618
+ artificial lift, wireline and cased-hole tools, fishing and milling, test
619
+ tools - ninety-six classes in nine categories. Point at a tool, or Tab to
620
+ it, for a one-line description; click, tap or press Enter for its tutorial:
621
+ what it is, where it runs, how it works, what it shows in the data, what to
622
+ watch, and what this program does with it, with the published figures
623
+ quoted from the pages they cite and the pages themselves. The tutorials
624
+ carry no numbers of their own; a figure on a tool's card is the cited page's
625
+ words, most often one maker's product, never a limit for the class. Your
626
+ **fleet** - the tools you actually run - goes in beside the classes, each
627
+ with its maker, model, serial and the datasheet that rates it
628
+ (`gea tools --action fleet-add --workspace C:\site --class pdm_motor
629
+ --maker ... --model ... --datasheet ...`, or from the tutorial), kept in the
630
+ workspace and audited. `gea tools --action classes`, `--action tutorial
631
+ --class drilling_jar`.
632
+
633
+ Below it are the program's two registers: the gauge library - every gauge
616
634
  with its source citation, ratings, what it measures, the telemetry interface
617
635
  it declares and its datasheet aging rate where the vendor published one -
618
636
  and the ports, the file formats read and the eleven live protocols spoken,
@@ -123,7 +123,7 @@ from .profile_catalog import (
123
123
  read_pangaea_txt,
124
124
  )
125
125
 
126
- __version__ = "0.30.1"
126
+ __version__ = "0.31.0"
127
127
  __all__ = [
128
128
  "aging_rate", "rate_psi_yr", "accuracy_psi",
129
129
  "Sensor", "SimulatorConfig", "DownholeEngine",
@@ -285,6 +285,17 @@ def main(argv=None) -> int:
285
285
  p_tl.add_argument("--station", type=str, action="append", default=None, help="a station as DEPTH_FT:TOOL, e.g. 9850:quartz_pt_geoq177_16k")
286
286
  p_tl.add_argument("--surface-temp-f", type=float, default=75.0); p_tl.add_argument("--temp-gradient-f-ft", type=float, default=0.018)
287
287
  p_tl.add_argument("--surface-pressure-psi", type=float, default=14.7); p_tl.add_argument("--pressure-gradient-psi-ft", type=float, default=0.465)
288
+ p_tl.add_argument("--action", choices=["classes", "tutorial", "fleet", "fleet-add", "fleet-remove"], default=None,
289
+ help="the downhole tool classes in use across the industry: classes (--category, --find), tutorial --class ID, and the workspace's own fleet (fleet, fleet-add, fleet-remove)")
290
+ p_tl.add_argument("--category", type=str, default=None, help="classes: one category (bits, drive, measure, bha, casing, completion, logging, fishing, testing)")
291
+ p_tl.add_argument("--find", type=str, default="", help="classes: words to look for in the name and description")
292
+ p_tl.add_argument("--class", dest="class_id", type=str, default=None, help="tutorial / fleet-add: the tool class id, e.g. pdm_motor")
293
+ p_tl.add_argument("--workspace", type=str, default=None, help="fleet actions: the workspace folder")
294
+ p_tl.add_argument("--maker", type=str, default=""); p_tl.add_argument("--model", type=str, default="")
295
+ p_tl.add_argument("--datasheet", type=str, default="", help="fleet-add: the datasheet that rates the tool - title and revision, or its URL (required)")
296
+ p_tl.add_argument("--serial", type=str, default=""); p_tl.add_argument("--od-in", type=float, default=None); p_tl.add_argument("--note", type=str, default="")
297
+ p_tl.add_argument("--id", type=str, default=None, help="fleet-remove: the fleet tool id (gea tools --action fleet lists them)")
298
+ p_tl.add_argument("--actor", type=str, default="cli")
288
299
  p_cc = sub.add_parser("comcat", help="USGS ComCat / any FDSN event service: --lat --lon --radius-km --start --end prints the text-format query to open; --file reads the export it returns")
289
300
  p_cc.add_argument("--lat", type=float, default=None); p_cc.add_argument("--lon", type=float, default=None); p_cc.add_argument("--radius-km", type=float, default=25.0)
290
301
  p_cc.add_argument("--start", type=str, default=None); p_cc.add_argument("--end", type=str, default=None); p_cc.add_argument("--min-mag", type=float, default=1.0)
@@ -2374,6 +2385,71 @@ def main(argv=None) -> int:
2374
2385
  elif a.cmd == "tools":
2375
2386
  import json as _json
2376
2387
  from . import tool_catalog as _TC
2388
+ if a.action:
2389
+ from . import tool_taxonomy as _TX
2390
+ from .cli import _safe_stdout
2391
+ _safe_stdout() # the cited figures carry fractions and degree signs
2392
+ if a.action == "classes":
2393
+ cs = _TX.classes(a.category, a.find)
2394
+ if a.category and a.category not in _TX.CATEGORY_NAMES:
2395
+ raise SystemExit(f"tools: no category {a.category!r}; one of {', '.join(_TX.CATEGORY_NAMES)}")
2396
+ if a.json:
2397
+ print(_json.dumps(cs, indent=1)); return 0
2398
+ sm = _TX.summary()
2399
+ print(f"{len(cs)} of {sm['classes']} tool classes; {sm['sources']} pages checked (fetched {sm['sources_fetched']}); {sm['figures']} published figures, each quoted from its page")
2400
+ last = None
2401
+ for t in cs:
2402
+ if t["category"] != last:
2403
+ print(f"\n{t['category_name']}"); last = t["category"]
2404
+ print(f" {t['id']:<24s} {t['name']}")
2405
+ print(f" {t['one_line']}")
2406
+ print("\n`gea tools --action tutorial --class ID` opens one.")
2407
+ return 0
2408
+ if a.action == "tutorial":
2409
+ if not a.class_id:
2410
+ raise SystemExit("tools: tutorial needs --class, e.g. --class pdm_motor (gea tools --action classes lists them)")
2411
+ try:
2412
+ if a.json:
2413
+ print(_json.dumps(_TX.tool_class(a.class_id), indent=1)); return 0
2414
+ print(_TX.tutorial_text(a.class_id))
2415
+ except KeyError as e:
2416
+ raise SystemExit(f"tools: {e.args[0]}")
2417
+ return 0
2418
+ if not a.workspace:
2419
+ raise SystemExit(f"tools: --action {a.action} needs --workspace, e.g. --workspace C:\\site")
2420
+ from .workspace import Workspace, WorkspaceError
2421
+ try:
2422
+ ws = Workspace(a.workspace)
2423
+ except WorkspaceError as e:
2424
+ raise SystemExit(f"tools: {e}")
2425
+ if a.action == "fleet":
2426
+ fl = _TX.fleet_list(ws.path)
2427
+ if a.json:
2428
+ print(_json.dumps(fl, indent=1)); return 0
2429
+ if not fl:
2430
+ print("the fleet is empty: gea tools --action fleet-add --workspace ... --class pdm_motor --maker ... --model ... --datasheet ...")
2431
+ for t in fl:
2432
+ print(f"{t['id']:<32s} {t['class_name']} - {t['maker']} {t['model']}" + (f" s/n {t['serial']}" if t['serial'] else '') + (f", {t['od_in']:g} in OD" if t['od_in'] else ''))
2433
+ print(f" datasheet: {t['datasheet']}")
2434
+ return 0
2435
+ if a.action == "fleet-add":
2436
+ try:
2437
+ rec = _TX.fleet_add(ws.path, a.class_id or "", a.maker, a.model, a.datasheet, serial=a.serial, od_in=a.od_in, note=a.note, actor=a.actor)
2438
+ except ValueError as e:
2439
+ raise SystemExit(f"tools: {e}")
2440
+ ws.audit(a.actor, 'fleet.add', {'id': rec['id'], 'class': rec['class_id'], 'datasheet': rec['datasheet']})
2441
+ print(f"added {rec['id']}: {rec['maker']} {rec['model']} ({rec['class_name']}); datasheet {rec['datasheet']}")
2442
+ return 0
2443
+ if a.action == "fleet-remove":
2444
+ if not a.id:
2445
+ raise SystemExit("tools: fleet-remove needs --id (gea tools --action fleet lists them)")
2446
+ try:
2447
+ rec = _TX.fleet_remove(ws.path, a.id)
2448
+ except ValueError as e:
2449
+ raise SystemExit(f"tools: {e}")
2450
+ ws.audit(a.actor, 'fleet.remove', {'id': rec['id'], 'class': rec['class_id']})
2451
+ print(f"removed {rec['id']}")
2452
+ return 0
2377
2453
  if a.rating or a.station:
2378
2454
  stations = []
2379
2455
  for spec in (a.station or []):
@@ -7856,6 +7856,155 @@ def section_by_edr(tmp: str) -> None:
7856
7856
  + (f" [failed: {', '.join(failed4)}]" if failed4 else ""))
7857
7857
 
7858
7858
 
7859
+
7860
+ def section_bz_tool_library(tmp: str) -> None:
7861
+ """Section BZ - the downhole tool library: every class of downhole tool in use across the industry, a one-line
7862
+ description on hover and a tutorial that opens on a click, the published figures quoted from the pages they cite and
7863
+ nothing more, and the operator's own fleet tied to the classes and to the datasheets that rate them."""
7864
+ import http.cookiejar
7865
+ import re as _re
7866
+ import subprocess as _sp
7867
+ import urllib.request
7868
+ import urllib.error
7869
+ from urllib.parse import urlparse
7870
+ from . import tool_taxonomy as TX
7871
+ from . import helplib as H
7872
+ from .client_reports import FORBIDDEN_TERMS
7873
+ from .tool_library import TOOL_LIBRARY
7874
+ from .workspace import Workspace
7875
+ from .service import Service, Users
7876
+ pkg = Path(__file__).parent
7877
+ d = Path(tmp, "bz"); d.mkdir()
7878
+
7879
+ def _raises(fn, exc, words=""):
7880
+ try:
7881
+ fn()
7882
+ except exc as e:
7883
+ return words in str(e)
7884
+ return False
7885
+
7886
+ sm = TX.summary()
7887
+ cls = list(TX.TAXONOMY.values())
7888
+ prose = lambda t: " ".join([t["one_line"]] + [t["tutorial"][p] for p in TX.PARTS])
7889
+ lowtier = _re.compile(r"(wikipedia\.org|rigzone\.com|drillingmanual\.com|petroleumacronyms|turbodrill\.com)$")
7890
+ figs = [f for t in cls for f in t["figures"]]
7891
+ c1 = {
7892
+ "breadth": sm["classes"] >= 90 and len(sm["categories"]) == 9 and all(c["classes"] >= 1 for c in sm["categories"])
7893
+ and {"pdm_motor", "rss_push", "mwd_mud_pulse", "lwd_gamma", "drilling_jar", "production_packer", "esp", "perforating_gun",
7894
+ "pdg", "wl_formation_tester", "cbl", "overshot", "dst"} <= set(TX.TAXONOMY),
7895
+ "hover": all(0 < len(t["one_line"]) <= 140 for t in cls),
7896
+ "tutorial": all(all(len(t["tutorial"][p]) > 20 for p in TX.PARTS) for t in cls) and TX.PARTS == ("what", "where", "how", "reads", "watch", "program"),
7897
+ "no_numbers_in_prose": not any(_re.search(r"\d", prose(t)) for t in cls),
7898
+ "words": not any(w in (t["name"] + " " + prose(t)).lower() for t in cls for w in FORBIDDEN_TERMS),
7899
+ "sources": all(t["sources"] for t in cls) and all(urlparse(x["url"]).scheme == "https" and x.get("publisher") for t in cls for x in t["sources"])
7900
+ and not any(lowtier.search(urlparse(x["url"]).netloc.lower()) for t in cls for x in t["sources"])
7901
+ and (pkg / "reference" / "tool_sources.json").is_file() and sm["sources"] >= 150 and sm["sources_fetched"] == "2026-10-14",
7902
+ "figures": len(figs) == sm["figures"] and len(figs) >= 150 and all(f.get("quote") and f.get("url") and f.get("publisher") and f.get("what") for f in figs)
7903
+ and not any("..." in f["quote"] for f in figs)
7904
+ and all(("not a limit for the class" in t["figures_note"]) if t["figures"] else ("supply your model's datasheet" in t["figures_note"]) for t in cls),
7905
+ "lookup": [t["id"] for t in TX.classes("drive")][:1] == ["pdm_motor"] and {t["id"] for t in TX.classes(None, "packer")} >= {"production_packer"}
7906
+ and TX.classes(None, "no such tool zzz") == [],
7907
+ "unknown": _raises(lambda: TX.tool_class("no_such_tool"), KeyError),
7908
+ "text": all(TX.PART_TITLES[p] + ": " in TX.tutorial_text("pdm_motor") for p in TX.PARTS) and "Sources (fetched 2026-10-14)" in TX.tutorial_text("pdm_motor")
7909
+ and "Published figures (" in TX.tutorial_text("agitator") and "8-12 Hz" in TX.tutorial_text("agitator"),
7910
+ "gauges": all(TX.GAUGE_CLASS_TO_TAXONOMY.get(t.tool_class) in TX.TAXONOMY for t in TOOL_LIBRARY.values()),
7911
+ }
7912
+ failed1 = [k for k, v in c1.items() if not v]
7913
+ ok(not failed1,
7914
+ "BZ1 the downhole tool library: at least ninety classes in nine categories from bits to test tools, each with a one-line description for the hover "
7915
+ "and a six-part tutorial for the pop-open; the prose carries no number at all and none of the words a client report may not; every class checked "
7916
+ "against at least one public page (none of them an encyclopaedia or a re-publisher); every published figure is the cited page's own words with its "
7917
+ "unit and page, never a limit for the class, and a class with none says to supply the datasheet; the classes searchable; an unknown class named; "
7918
+ "every gauge in the gauge library opens its class's tutorial"
7919
+ + (f" [failed: {', '.join(failed1)}]" if failed1 else ""))
7920
+
7921
+ wsp = str(d / "ws"); Workspace.create(wsp, "Pad 3", actor="tester")
7922
+ e_ds = _raises(lambda: TX.fleet_add(wsp, "pdm_motor", "Acme", "M1", ""), ValueError, "datasheet")
7923
+ e_cls = _raises(lambda: TX.fleet_add(wsp, "warp_drive", "Acme", "M1", "sheet"), ValueError, "no tool class")
7924
+ r1 = TX.fleet_add(wsp, "pdm_motor", "Acme", "M1", "Acme M1 datasheet rev B", serial="A100", od_in=6.75)
7925
+ e_dup = _raises(lambda: TX.fleet_add(wsp, "pdm_motor", "Acme", "M1", "Acme M1 datasheet rev B", serial="A100"), ValueError, "already")
7926
+ users = Users(str(Path(wsp, "users.json"))); users.add("op", "operator-pass-1", "operator"); users.add("v", "viewer-pass-1", "viewer")
7927
+ svc = Service(wsp, port=0, scheduler=False).start()
7928
+ base_url = svc.url.rstrip("/")
7929
+
7930
+ def session():
7931
+ o = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(http.cookiejar.CookieJar()))
7932
+
7933
+ def call(method, path, body=None):
7934
+ req = urllib.request.Request(base_url + path, method=method, data=(json.dumps(body).encode() if body is not None else None))
7935
+ req.add_header("Content-Type", "application/json"); req.add_header("X-GEA-Action", "1")
7936
+ try:
7937
+ with o.open(req, timeout=60) as rr_:
7938
+ return rr_.status, json.loads(rr_.read())
7939
+ except urllib.error.HTTPError as e:
7940
+ return e.code, json.loads(e.read())
7941
+ return call
7942
+ try:
7943
+ view, op = session(), session()
7944
+ view("POST", "/api/login", {"name": "v", "password": "viewer-pass-1"}); op("POST", "/api/login", {"name": "op", "password": "operator-pass-1"})
7945
+ st_t, tx = view("GET", "/api/tools/taxonomy")
7946
+ st_q, txq = view("GET", "/api/tools/taxonomy?q=jar")
7947
+ st_v, _ = view("POST", "/api/tools/fleet", {"class_id": "esp", "maker": "Acme", "model": "P2", "datasheet": "Acme P2 sheet"})
7948
+ st_nods, nods = op("POST", "/api/tools/fleet", {"class_id": "esp", "maker": "Acme", "model": "P2", "datasheet": ""})
7949
+ st_add, added = op("POST", "/api/tools/fleet", {"class_id": "esp", "maker": "Acme", "model": "P2", "datasheet": "Acme P2 sheet rev A", "od_in": "5.38"})
7950
+ st_fl, fl = view("GET", "/api/tools/fleet")
7951
+ st_rm, _ = op("POST", f"/api/tools/fleet/{r1['id']}/remove", {})
7952
+ st_rm2, _ = op("POST", "/api/tools/fleet/nothing-here/remove", {})
7953
+ finally:
7954
+ svc.stop()
7955
+ audit = Path(wsp, "records", "audit.jsonl").read_text(encoding="utf-8")
7956
+ c2 = {
7957
+ "fleet_rules": e_ds and e_cls and e_dup and r1["id"] == "acme-m1-a100" and r1["class_name"] == TX.TAXONOMY["pdm_motor"]["name"] and r1["od_in"] == 6.75
7958
+ and Path(wsp, "config", "fleet.json").is_file(),
7959
+ "api": st_t == 200 and len(tx["classes"]) == sm["classes"] and [p[0] for p in tx["parts"]] == list(TX.PARTS) and tx["summary"]["figures"] == sm["figures"]
7960
+ and st_q == 200 and {c["id"] for c in txq["classes"]} >= {"drilling_jar", "jar_accelerator"} and len(txq["classes"]) < 10
7961
+ and tx["fleet"] and tx["fleet"][0]["id"] == "acme-m1-a100",
7962
+ "roles": st_v == 403 and st_nods == 400 and "datasheet" in nods.get("error", "") and st_add == 200 and added["od_in"] == 5.38
7963
+ and st_fl == 200 and {t["id"] for t in fl["tools"]} == {"acme-m1-a100", "acme-p2"} and st_rm == 200 and st_rm2 == 404
7964
+ and [t["id"] for t in TX.fleet_list(wsp)] == ["acme-p2"],
7965
+ "audit": '"fleet.add"' in audit and '"fleet.remove"' in audit and "Acme P2 sheet rev A" in audit,
7966
+ }
7967
+ failed2 = [k for k, v in c2.items() if not v]
7968
+ ok(not failed2,
7969
+ "BZ2 the fleet: a tool of yours needs its class and its datasheet citation, and is not added twice; it is kept in the workspace's config; the API "
7970
+ "serves the classes, the tutorial parts and the fleet to any signed-in user, adds and removes for an operator and not a viewer, says why an "
7971
+ "addition without a datasheet is turned away, and every addition and removal is in the audit log"
7972
+ + (f" [failed: {', '.join(failed2)}]" if failed2 else ""))
7973
+
7974
+ page_src = (pkg / "web" / "app.html").read_text(encoding="utf-8")
7975
+ help_md = (pkg / "help" / "tools.md").read_text(encoding="utf-8")
7976
+ r_cls = _sp.run([sys.executable, "-m", "gea", "tools", "--action", "classes"], capture_output=True, text=True)
7977
+ r_cat = _sp.run([sys.executable, "-m", "gea", "tools", "--action", "classes", "--category", "fishing"], capture_output=True, text=True)
7978
+ r_tut = _sp.run([sys.executable, "-m", "gea", "tools", "--action", "tutorial", "--class", "drilling_jar"], capture_output=True, text=True)
7979
+ r_none = _sp.run([sys.executable, "-m", "gea", "tools", "--action", "tutorial"], capture_output=True, text=True)
7980
+ r_bad = _sp.run([sys.executable, "-m", "gea", "tools", "--action", "tutorial", "--class", "warp_drive"], capture_output=True, text=True)
7981
+ r_add = _sp.run([sys.executable, "-m", "gea", "tools", "--action", "fleet-add", "--workspace", wsp, "--class", "drilling_jar", "--maker", "Acme",
7982
+ "--model", "J9", "--datasheet", "Acme J9 sheet rev C"], capture_output=True, text=True)
7983
+ r_nods = _sp.run([sys.executable, "-m", "gea", "tools", "--action", "fleet-add", "--workspace", wsp, "--class", "drilling_jar", "--maker", "Acme",
7984
+ "--model", "J10"], capture_output=True, text=True)
7985
+ r_list = _sp.run([sys.executable, "-m", "gea", "tools", "--action", "fleet", "--workspace", wsp], capture_output=True, text=True)
7986
+ r_nows = _sp.run([sys.executable, "-m", "gea", "tools", "--action", "fleet"], capture_output=True, text=True)
7987
+ c3 = {
7988
+ "page": all(x in page_src for x in ("Downhole tool library", "class=\"tl-chip\"", 'role="tooltip"', "aria-haspopup=\"dialog\"", ".tl-chip:focus-visible .tl-tip",
7989
+ "@media (hover:none)", "showModal()", "dialog.tl-dlg::backdrop", "/api/tools/taxonomy", "/api/tools/fleet", "Add one of yours",
7990
+ "Your fleet", "tl-open", "Esc closes it")),
7991
+ "cli": r_cls.returncode == 0 and f"{sm['classes']} of {sm['classes']} tool classes" in r_cls.stdout and "Fishing, milling and intervention" in r_cls.stdout
7992
+ and r_cat.returncode == 0 and "overshot" in r_cat.stdout and "pdm_motor" not in r_cat.stdout
7993
+ and r_tut.returncode == 0 and "What it is: " in r_tut.stdout and "In this program: " in r_tut.stdout
7994
+ and r_none.returncode != 0 and "--class pdm_motor" in (r_none.stderr + r_none.stdout) and "<" not in (r_none.stderr + r_none.stdout)
7995
+ and r_bad.returncode != 0 and "no tool class 'warp_drive'" in (r_bad.stderr + r_bad.stdout),
7996
+ "cli_fleet": r_add.returncode == 0 and "added acme-j9" in r_add.stdout and r_nods.returncode != 0 and "datasheet" in (r_nods.stderr + r_nods.stdout)
7997
+ and r_list.returncode == 0 and "Acme J9 sheet rev C" in r_list.stdout and r_nows.returncode != 0 and "needs --workspace" in (r_nows.stderr + r_nows.stdout),
7998
+ "help": not H.check("tools") and "tutorial" in help_md and "fleet" in help_md and "the tutorials carry no numbers at all" in help_md.split("will not call a measurement")[1],
7999
+ }
8000
+ failed3 = [k for k, v in c3.items() if not v]
8001
+ ok(not failed3,
8002
+ "BZ3 the page and the command line: a chip per class that shows its description on hover and on keyboard focus (not on a touch screen, where a tap "
8003
+ "opens it), a tutorial dialog that opens on click, tap or Enter and closes on Esc or the backdrop, a find box and a category filter, the fleet card, "
8004
+ "the gauge library's Tutorial buttons; `gea tools --action classes | tutorial | fleet | fleet-add`, each refusing a missing argument by name without "
8005
+ "a placeholder; the help page"
8006
+ + (f" [failed: {', '.join(failed3)}]" if failed3 else ""))
8007
+
7859
8008
  def main() -> int:
7860
8009
  print("GEA-Program - ACCEPTANCE SUITE (the product gate)")
7861
8010
  # a handle a job subprocess still holds at the end must not turn a finished gate into a traceback on Windows:
@@ -7936,6 +8085,7 @@ def main() -> int:
7936
8085
  section_bw_catalog_map(tmp)
7937
8086
  section_bx_pasteable(tmp)
7938
8087
  section_by_edr(tmp)
8088
+ section_bz_tool_library(tmp)
7939
8089
  if _FAILS:
7940
8090
  print(f"[ACCEPTANCE] {len(_FAILS)} FAILURES ({_PASS} passed):")
7941
8091
  for f in _FAILS:
@@ -0,0 +1,11 @@
1
+ # Tools and ports
2
+
3
+ > What this program knows how to measure with, what is run in the hole around it, and what it knows how to speak. The downhole tool library is every class of downhole tool in use across the industry - bits, motors and steerable systems, MWD and LWD, the drill string and its subs, casing and cementing equipment, completion and artificial lift, wireline and cased-hole tools, fishing and milling, test tools - each with a one-line description on hover and a tutorial that opens on a click; the fleet is your own tools in those classes, each tied to its datasheet. The gauge library is the downhole and surface tools - each with the citation its numbers came from, the conditions it is rated for, and the telemetry interface it declares; the port registry is the file formats and live protocols that bring a tool's readings in. The page draws the line between them: a tool declares an interface, a port speaks one, and a tool whose interface no port in this build speaks is named rather than hidden.
4
+
5
+ **The command**: the page is Tools & ports on the dashboard. Point at a tool class (or Tab to it) for its one-line description; click, tap or press Enter for the tutorial - what it is, where it runs, how it works, what it shows in the data, what to watch, what this program does with it, the published figures and the pages it was checked against; Esc or Close puts it away. `gea tools --action classes` lists the classes (`--category measure`, `--find packer`), `gea tools --action tutorial --class pdm_motor` prints one, `gea tools --action fleet-add --workspace C:\site --class pdm_motor --maker Acme --model M1 --serial A100 --datasheet "Acme M1 datasheet rev B"` adds a tool of yours (an operator may also add it from the tutorial), `--action fleet` lists them and `--action fleet-remove --id ...` takes one out. `gea tools` alone prints the same register at the command line (`--json` for the machine record, `--rating --station 9850:quartz_pt_geoq177_16k ...` for the rating check). A tool whose vendor published no numbers is listed as PARAMETERS_USER_SUPPLIED: `gea config` takes your own datasheet (`load_gauge_spec_json`) and the tool is then simulated and aged from it. The live protocols each name what the site must supply before they run and what to rehearse against - `gea wits0-sim`, `gea etp-sim`, `gea seedlink-sim`, or the stand-in slave, outstation, device and historian the field ports ship with.
6
+
7
+ **What it writes**: the fleet, to `config\fleet.json` in the workspace, every addition and removal in the audit log; everything else on the page is a register, not a record. Per tool class it states the tutorial, the published figures - each the cited page's own words and unit, quoted as read on the date the pages were fetched, most of them one maker's product and never a limit for the class - and the sources. Per gauge it states: the class, what it measures, the temperature and pressure ratings, the published aging rate in %FS/yr where the datasheet gives one (and the reason there is none where it does not), the interface it declares, the ports that can carry it, and its source. Per port: the transport, the status (IMPLEMENTED, or DECLARED_SITE_DETAILS_REQUIRED with what is missing), and what it speaks to. The rating check returns, per station, the temperature and pressure at that depth, the tool's ratings and whether the station is within them, with the basis of the conditions printed beside the answer.
8
+
9
+ **The number to check**: a published figure against the page it cites, and your own tool's rating against its datasheet, never against the class's figures; the aging rate against your own datasheet before you trust a drift report built on it, and the rating check's per-station temperature against the tool's rating - the check that catches a 177 °C gauge hung in a 233 °C zone before the well does.
10
+
11
+ **What this page will not call a measurement**: a figure for a whole class of tools - the tutorials carry no numbers at all, and every number on a tool's card is quoted from the page it cites; a rating for a fleet tool its datasheet does not give - the fleet carries the datasheet citation and nothing more unless you give the numbers; a vendor number nobody published - a tool with no datasheet rate carries none and raises rather than inventing one, and the page says PARAMETERS_USER_SUPPLIED. A rating as a prediction - a station within its ratings is arithmetic on the vendor's number and the declared conditions, not a promise the tool survives. The conditions themselves - without a well profile they are the gradients declared on the page, and the answer prints which basis it used. A port as a connection - a port listed here speaks a protocol; whether the site's own device answers is what the Patch panel shows.
@@ -43,7 +43,7 @@ INDEX: List[tuple] = [
43
43
  ('edr', 'The drilling recorder', 'the rig\'s one-second EDR export read as delivered - sections, depths, hours on bottom, the rate of penetration, the recorder\'s MD-TVD table - and what the record will not say'),
44
44
  ('dlis', 'The DLIS log', 'a well log as it is delivered (API RP66 V1), read as the standard lays it out: the frames, the channels, what was skipped; into the strata survey'),
45
45
  ('historian', 'The historian pull', 'an operator\'s gauge history out of the PI System through PI Web API, read-only, every value with its archive time and flags'),
46
- ('tools', 'Tools and ports', 'the downhole and surface tools this program knows, each with its citation and ratings, the formats and protocols that bring their readings in, and the rating check on a tool string'),
46
+ ('tools', 'Tools and ports', 'every class of downhole tool in use across the industry with a hover description and a pop-open tutorial, your own fleet with its datasheets, the gauges this program reads with their citations and ratings, the formats and protocols that bring readings in, and the rating check on a tool string'),
47
47
  ('field-ports', 'The field ports', 'Modbus RTU on the serial line, DNP3 from the pad RTU, HART-IP from the transmitter itself - read-only, polled, with the stand-ins to rehearse against'),
48
48
  ('slip', 'Slip tendency on the mapped faults', 'the declared stress state resolved on each mapped fault around a well: the slip tendency, the pressure to slip, the World Stress Map as the SHmax source, the published Hennings values beside'),
49
49
  ('interval', 'The interval against the mapped tops', 'the declared disposal interval, subsea, beside each formation-top bracket; the depth tier against the mapped base; the catalogue events against the mapped faults'),