gea-program 0.76.0__tar.gz → 0.77.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.
- {gea_program-0.76.0/gea_program.egg-info → gea_program-0.77.0}/PKG-INFO +33 -6
- {gea_program-0.76.0 → gea_program-0.77.0}/README.md +32 -5
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/__init__.py +1 -1
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/__main__.py +16 -3
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/acceptance_tests.py +274 -9
- gea_program-0.77.0/gea/driller_link.py +278 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/IT_SECURITY.md +9 -0
- gea_program-0.77.0/gea/help/driller.md +13 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/install.md +2 -2
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/reader.md +1 -1
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/recorder.md +1 -1
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/tutorial/01-install.md +2 -2
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/tutorial/19-dossier-reader.md +1 -1
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/tutorial/22-updates.md +1 -1
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/tutorial/25-install-recorder.md +2 -2
- gea_program-0.77.0/gea/help/tutorial/28-driller-office.md +24 -0
- gea_program-0.77.0/gea/help/tutorial/29-driller-rig.md +21 -0
- gea_program-0.77.0/gea/help/tutorial.md +13 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/vpn.md +1 -1
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/helplib.py +2 -1
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/service.py +26 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/tutorial.py +2 -1
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/updates.py +3 -3
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/vpn.py +2 -1
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/web/app.html +29 -1
- {gea_program-0.76.0 → gea_program-0.77.0/gea_program.egg-info}/PKG-INFO +33 -6
- {gea_program-0.76.0 → gea_program-0.77.0}/gea_program.egg-info/SOURCES.txt +4 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/pyproject.toml +1 -1
- gea_program-0.76.0/gea/help/tutorial.md +0 -13
- {gea_program-0.76.0 → gea_program-0.77.0}/LICENSE +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/BENCH_TEST_PROTOCOL.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/accuracy_statement.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/alarm_engine.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/alerts.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/backup.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/bench.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/bit_seismic.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/blind_harness.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/casing_design.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/acex_lomonosov_age_depth_model.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/acex_lomonosov_age_depth_model.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/agassiz77_canada_temperature.csv +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/agassiz77_canada_temperature.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/barbados_110_consolidation.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/barbados_110_consolidation.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/bengal_u1452_grain_size.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/bengal_u1452_grain_size.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/blake_164_methane_isotopes.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/blake_164_methane_isotopes.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/collingwood_1_28_ks_complete.las +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/collingwood_1_28_ks_complete.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/costa_rica_odp_friction_envelope.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/costa_rica_odp_friction_envelope.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/dsdp_504b_physical_properties.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/dsdp_504b_physical_properties.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/dsdp_504b_sound_velocity.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/dsdp_504b_sound_velocity.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/elgygytgyn_5011_turbidites.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/elgygytgyn_5011_turbidites.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/epica_domec_co2_800kyr.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/epica_domec_co2_800kyr.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/fram_909_organic_petrography.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/fram_909_organic_petrography.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/gbr_325_coral_uth_ages.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/gbr_325_coral_uth_ages.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/gisp2_greenland_temperature.csv +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/gisp2_greenland_temperature.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/gom_308_t2p_insitu.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/gom_308_t2p_insitu.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/guaymas_385_dom_d13c.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/guaymas_385_dom_d13c.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/hikurangi_u1520_friction_insitu.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/hikurangi_u1520_friction_insitu.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/iodp_u1324_pore_pressure.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/iodp_u1324_pore_pressure.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/jfast_c0019_slow_slip_events.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/jfast_c0019_slow_slip_events.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/kennetcook_2_p129_excerpt.las +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/kennetcook_2_p129_excerpt.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/ktb_hb_bhgm_density.dat +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/ktb_hb_bhgm_density.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/ktb_hb_complog_6020_excerpt.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/ktb_hb_complog_6020_excerpt.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/ktb_hb_hlog246_temperature.dat +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/ktb_hb_hlog246_temperature.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/ktb_hb_rockmech_compress.dat +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/ktb_hb_rockmech_compress.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.dat +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/ktb_vb_rockmech_compress.dat +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/ktb_vb_rockmech_compress.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/ktb_vb_vlog251_temperature.dat +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/ktb_vb_vlog251_temperature.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/l06_06_nl_survey.csv +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/l06_06_nl_survey.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/l07_01_nl_excerpt.las +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/l07_01_nl_excerpt.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/mariana_1200_serpentinite_geochem.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/mariana_1200_serpentinite_geochem.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/med_160_sapropels.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/med_160_sapropels.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/nankai_megasplay_shear_strength.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/nankai_megasplay_shear_strength.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/odp_1027b_thermal_conductivity.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/odp_1027b_thermal_conductivity.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/odp_1027c_cork_temperature.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/odp_1027c_cork_temperature.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/odp_1165b_thermal_conductivity.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/odp_1165b_thermal_conductivity.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/odp_504b_dike_elastic_moduli.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/odp_504b_dike_elastic_moduli.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/odp_504b_leg137_borehole_fluids.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/odp_504b_leg137_borehole_fluids.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/peru_201_sulfate_reduction.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/peru_201_sulfate_reduction.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/scorpio_e1_sa_excerpt.las +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/scorpio_e1_sa_excerpt.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/sumatra_362_cohesion.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/sumatra_362_cohesion.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/university_6_17_no1_tx_excerpt.las +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/university_6_17_no1_tx_excerpt.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/ursa_308_xrd_mineralogy.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/ursa_308_xrd_mineralogy.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/volve_15_9_19_sr_excerpt.las +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/volve_15_9_19_sr_excerpt.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/volve_15_9_19a_core_excerpt.csv +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/volve_15_9_19a_core_excerpt.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/volve_f12_f14_production_excerpt.csv +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/volve_f12_f14_production_excerpt.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/walvis_208_petm_carbonate.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/walvis_208_petm_carbonate.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/woodlark_1109_rock_eval.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog/woodlark_1109_rock_eval.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog_map.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/catalog_register.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/certificates.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/cli.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/client_reports.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/collision.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/config_versioning.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/conformance.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/control_room.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/correlation.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/dashboard.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/declarations.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/decline.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/deviation.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/dlis.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/dnp3.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/doctor.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/dossier.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/dossier_verify.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/downhole_engine.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/drift_monitor.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/drill_string.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/earth_model.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/economics.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/ed25519.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/edr.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/elevation.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/etp.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/etp12_schemas.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/example_register_map.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/fat_sat.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/field_pull.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/files.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/fixtures/README.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/fixtures/comcat_delaware_basin_2026-09.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/fixtures/comcat_mahoning_1990-2026.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/fixtures/comcat_youngstown_2011-2012.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/fixtures/ne_110m_coastline.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/follower.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/forward_model.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/frac_hits.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/friction_priors.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/gamma.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/gauge_aging.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/gauge_specs.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/geodesy.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/geomag.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/gravity_reference.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/hartip.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/TESTER_GUIDE.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/alarms.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/alerts.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/audit-update.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/backup.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/bit-image.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/casing.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/catalog.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/charts.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/collision.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/company-sign-in.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/conformance.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/control-room.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/data-in.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/declare.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/decline.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/dlis.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/doctor.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/dossier.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/drift.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/drillstring.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/economics.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/edr.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/etp.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/field-ports.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/files.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/frac-hits.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/historian.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/https.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/hydraulics.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/instruments.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/interval.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/invoice-check.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/map.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/month-end.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/notifications.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/opseis.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/osdu.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/pad-summary.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/patches.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/penetrator.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/plan.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/pore-pressure.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/ppdm.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/quakeml.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/quality.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/records.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/report-history.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/rig-time.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/rocks.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/seedlink.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/seismic.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/setup.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/simulation.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/site.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/sites.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/slip.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/soak.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/sra.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/start.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/structure.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/tools.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/torque-drag.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/transients.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/tutorial/02-sign-in.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/tutorial/03-site.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/tutorial/04-add-well.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/tutorial/05-records.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/tutorial/06-well-page.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/tutorial/07-declare.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/tutorial/08-patches.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/tutorial/09-alarms.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/tutorial/10-control-room.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/tutorial/11-summary-month.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/tutorial/12-where-the-well-is.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/tutorial/13-drilling-pages.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/tutorial/14-production-pages.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/tutorial/15-seismic.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/tutorial/16-seismicity.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/tutorial/17-recorder-office.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/tutorial/18-reports.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/tutorial/20-admin.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/tutorial/21-upkeep.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/tutorial/23-vpn.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/tutorial/24-the-box.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/tutorial/26-monitor.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/tutorial/27-mirror-vpn.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/upkeep.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/vibration.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/well-report.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/well-tests.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/help/well3d.md +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/housekeeping.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/hydraulics.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/icon.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/interval.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/inverse_engine.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/invoice_check.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/jobs.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/launcher.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/live_ports.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/loadtest.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/matplotlib_demo.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/modbus.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/modbus_rtu.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/model_card.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/month_end.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/mqtt_port.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/notify.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/oidc.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/oidc_mock.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/op_seismicity.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/opcua_port.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/operator_app.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/osdu.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/pad_summary.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/patches.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/pdf_report.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/penetrator.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/permits.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/piwebapi.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/pore_pressure.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/ports.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/ppdm.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/profile_catalog.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/project.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/qt6_downhole_app.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/quakeml.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reader.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reader_app.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reconciler.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/recorder_link.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/IU_ANMO_10_BHZ_response.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/IU_ANMO_10_BHZ_response.xml +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/WMM2025.COF +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/eia_henry_hub_daily.csv.gz +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/eia_prices.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/eia_wti_daily.csv.gz +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/iscwsa_rev4_example.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/iscwsa_rev5_example.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/l0701_sonic_gr.las.gz +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/l0701_sonic_gr.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/libmseed_steim.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/libmseed_steim1_4096.mseed +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/libmseed_steim2_4096.mseed +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/libmseed_steim2_512.mseed +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/mahoning_example.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/mud_motor_specs.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/owsg_tool_models.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/penetrator_ratings.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/seismicity_protocols.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/tool_sources.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/us_outline.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/us_outline.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/volve_3d.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/volve_f4_interpretation.las.gz +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/volve_f4_logs.provenance.json +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/volve_f4_lwd.las.gz +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/volve_surfaces.json.gz +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/volve_traj_F-10.xml.gz +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/volve_traj_F-4.xml.gz +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/volve_traj_F-5_12.25in.xml.gz +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/volve_traj_F-5_17.5in.xml.gz +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/volve_traj_F-5_36in.xml.gz +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/volve_traj_F-5_8.5in.xml.gz +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/reference/volve_well_picks.csv.gz +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/report_history.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/rig_state.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/rock_inventory.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/sample_record.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/sample_well_profile.csv +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/sbom.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/seedlink.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/segy.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/seismic.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/seismic_array.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/seismic_assoc.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/seismic_detect.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/seismic_film.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/seismic_harmonic.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/seismic_qc.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/seismic_response.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/seismic_signature.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/seismic_track.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/seismic_uncertainty.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/seismic_unlisted.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/seismic_watch.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/sensor_swap.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/series_cache.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/service_life.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/setup_checklist.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/shapefile.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/shell.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/shut_in.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/simulation.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/site_map.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/sla_report.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/slip.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/soak.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/sra.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/store_forward.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/strata_join.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/structure.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/supervisor.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/survey_cmd.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/survey_view.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/telemetry.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/timestamp.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/tls.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/tool_catalog.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/tool_library.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/tool_taxonomy.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/torque_drag.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/transient.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/tray.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/vibration.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/web/reader.html +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/well3d.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/well_assembler.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/well_records.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/well_report.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/well_test_validation.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/wellplan.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/wellpos.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/winident.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/wits0.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/witsml.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/workspace.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/workspaces.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/x25519.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea/xlsx_read.py +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea_program.egg-info/dependency_links.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea_program.egg-info/entry_points.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea_program.egg-info/requires.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/gea_program.egg-info/top_level.txt +0 -0
- {gea_program-0.76.0 → gea_program-0.77.0}/setup.cfg +0 -0
- {gea_program-0.76.0 → gea_program-0.77.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.
|
|
3
|
+
Version: 0.77.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
|
|
@@ -463,9 +463,36 @@ keeps them byte for byte and makes the array and electrode stations of
|
|
|
463
463
|
them. `gea help recorder`; the box's README has the parts, the wiring and
|
|
464
464
|
the clock.
|
|
465
465
|
|
|
466
|
+
### GEA Driller: the directional driller's agent
|
|
467
|
+
|
|
468
|
+
GEA Driller (`driller/`; `GEA-Driller-<version>.tar.gz` on every release;
|
|
469
|
+
since 0.77.0; `gea help driller`) is the program on the rig PC. It reads
|
|
470
|
+
the EDR's WITS0 feed and the pre-drill model of the target layer and, every
|
|
471
|
+
30 ft of new hole, recommends in the driller's units what to do next:
|
|
472
|
+
build, drop or hold and by how much (toolface and steering ratio for a
|
|
473
|
+
rotary steerable system), the weight on bit, the rotary speed, the flow
|
|
474
|
+
rate, and whether to drill on, circulate, or ream and wash first - with its
|
|
475
|
+
reasons and the confidence of each choice. The driller accepts, rejects or
|
|
476
|
+
records what was done instead, by name; every recommendation, answer and
|
|
477
|
+
command is on record with its hash, and GEA pulls the records into the
|
|
478
|
+
well from the **Drill string** tab's card (`gea workspace --path C:\site
|
|
479
|
+
--action driller-pull --box http://192.168.1.60:8790 --well SWD-1`). The
|
|
480
|
+
agent is a policy trained by proximal policy optimization in a physics
|
|
481
|
+
twin of the lateral - the layer rolling with dip, undulation and faults,
|
|
482
|
+
the gamma and the deep-resistivity boundary the tools read of it, the
|
|
483
|
+
steering tool, the bit, the hydraulics, the hole - on scenes drawn fresh,
|
|
484
|
+
judged against a textbook driller on scenes it never saw; the figures of
|
|
485
|
+
that judgement are a simulation's and are labelled so. Advisory by
|
|
486
|
+
default; the closed loop ships as a design with a switch, armed by a named
|
|
487
|
+
operator for one section, disarming itself on a stale feed, a crossed
|
|
488
|
+
limit or the section's end, through a downlink that keeps every command and
|
|
489
|
+
sends none - no vendor's protocol ships with this version. Before there is
|
|
490
|
+
a rig PC, **Start the twin as the rig** on the same card runs the driller's
|
|
491
|
+
program on the office PC with a scene drilling itself.
|
|
492
|
+
|
|
466
493
|
### The tutorial
|
|
467
494
|
|
|
468
|
-
Every step of GEA and the programs around it, as
|
|
495
|
+
Every step of GEA and the programs around it, as 29 lessons on the
|
|
469
496
|
**Tutorial** tab (since 0.76.0; `gea help tutorial`): the office's lessons
|
|
470
497
|
first - install, sign in, set up the site, bring wells and data in, the
|
|
471
498
|
well page, the declarations sheet, the patch panel, alarms and
|
|
@@ -475,7 +502,7 @@ seismic, the recorder from the office, reports, the signed dossier and the
|
|
|
475
502
|
Reader, users and HTTPS, backups and the gate, new versions from inside
|
|
476
503
|
the program, GEA-VPN - and the pad attendant's after: the box and its
|
|
477
504
|
parts, installing the recorder on the Pi, the monitor, the USB mirror and
|
|
478
|
-
joining the VPN. Each lesson names who it is for, the page it is done on
|
|
505
|
+
joining the VPN - and GEA Driller from the office and on the rig PC. Each lesson names who it is for, the page it is done on
|
|
479
506
|
(a button opens it), how long it takes, the numbered steps with the
|
|
480
507
|
buttons as the page names them, and how you know it worked; each account
|
|
481
508
|
ticks lessons off. **Print the handout** gives the whole course as one
|
|
@@ -800,7 +827,7 @@ unsigned, the key hand-overs - and shows the reports as they were signed. A
|
|
|
800
827
|
reader made from the workspace knows the site's key fingerprints, so it
|
|
801
828
|
says whether a dossier is the site's; it allows no network request, and it
|
|
802
829
|
leaves the trusted time-stamp to `verify_dossier.py`. For a client who wants
|
|
803
|
-
it installed, every release also carries `GEA-Reader-Setup-0.
|
|
830
|
+
it installed, every release also carries `GEA-Reader-Setup-0.77.0.exe`: GEA
|
|
804
831
|
Reader as a Windows program of its own - its own icon and taskbar button,
|
|
805
832
|
Check with GEA Reader on a dossier's right-click menu, fingerprints the client
|
|
806
833
|
saves kept on that computer, nothing of GEA-Program. `gea help reader`.
|
|
@@ -1565,7 +1592,7 @@ attaches the zips to the GitHub release of that tag.
|
|
|
1565
1592
|
|
|
1566
1593
|
### The Windows installer
|
|
1567
1594
|
|
|
1568
|
-
Every release also carries `GEA-Program-Setup-0.
|
|
1595
|
+
Every release also carries `GEA-Program-Setup-0.77.0.exe` (for 0.77.0): the
|
|
1569
1596
|
same Windows kit installed like any Windows program, for the signed-in user
|
|
1570
1597
|
alone and with no administrator rights (`%LOCALAPPDATA%\Programs\GEA-Program`).
|
|
1571
1598
|
It asks for the site workspace (an existing one such as `C:\site` is used as
|
|
@@ -1584,7 +1611,7 @@ it, removes the program and leaves the workspace. Silent, for a site's
|
|
|
1584
1611
|
software deployment:
|
|
1585
1612
|
|
|
1586
1613
|
```
|
|
1587
|
-
GEA-Program-Setup-0.
|
|
1614
|
+
GEA-Program-Setup-0.77.0.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /WORKSPACE="C:\site" /SITENAME="Pad 3" /TASKS="desktopicon"
|
|
1588
1615
|
```
|
|
1589
1616
|
|
|
1590
1617
|
The setup is built by Inno Setup 6 from `tools/installer.iss` in the same
|
|
@@ -424,9 +424,36 @@ keeps them byte for byte and makes the array and electrode stations of
|
|
|
424
424
|
them. `gea help recorder`; the box's README has the parts, the wiring and
|
|
425
425
|
the clock.
|
|
426
426
|
|
|
427
|
+
### GEA Driller: the directional driller's agent
|
|
428
|
+
|
|
429
|
+
GEA Driller (`driller/`; `GEA-Driller-<version>.tar.gz` on every release;
|
|
430
|
+
since 0.77.0; `gea help driller`) is the program on the rig PC. It reads
|
|
431
|
+
the EDR's WITS0 feed and the pre-drill model of the target layer and, every
|
|
432
|
+
30 ft of new hole, recommends in the driller's units what to do next:
|
|
433
|
+
build, drop or hold and by how much (toolface and steering ratio for a
|
|
434
|
+
rotary steerable system), the weight on bit, the rotary speed, the flow
|
|
435
|
+
rate, and whether to drill on, circulate, or ream and wash first - with its
|
|
436
|
+
reasons and the confidence of each choice. The driller accepts, rejects or
|
|
437
|
+
records what was done instead, by name; every recommendation, answer and
|
|
438
|
+
command is on record with its hash, and GEA pulls the records into the
|
|
439
|
+
well from the **Drill string** tab's card (`gea workspace --path C:\site
|
|
440
|
+
--action driller-pull --box http://192.168.1.60:8790 --well SWD-1`). The
|
|
441
|
+
agent is a policy trained by proximal policy optimization in a physics
|
|
442
|
+
twin of the lateral - the layer rolling with dip, undulation and faults,
|
|
443
|
+
the gamma and the deep-resistivity boundary the tools read of it, the
|
|
444
|
+
steering tool, the bit, the hydraulics, the hole - on scenes drawn fresh,
|
|
445
|
+
judged against a textbook driller on scenes it never saw; the figures of
|
|
446
|
+
that judgement are a simulation's and are labelled so. Advisory by
|
|
447
|
+
default; the closed loop ships as a design with a switch, armed by a named
|
|
448
|
+
operator for one section, disarming itself on a stale feed, a crossed
|
|
449
|
+
limit or the section's end, through a downlink that keeps every command and
|
|
450
|
+
sends none - no vendor's protocol ships with this version. Before there is
|
|
451
|
+
a rig PC, **Start the twin as the rig** on the same card runs the driller's
|
|
452
|
+
program on the office PC with a scene drilling itself.
|
|
453
|
+
|
|
427
454
|
### The tutorial
|
|
428
455
|
|
|
429
|
-
Every step of GEA and the programs around it, as
|
|
456
|
+
Every step of GEA and the programs around it, as 29 lessons on the
|
|
430
457
|
**Tutorial** tab (since 0.76.0; `gea help tutorial`): the office's lessons
|
|
431
458
|
first - install, sign in, set up the site, bring wells and data in, the
|
|
432
459
|
well page, the declarations sheet, the patch panel, alarms and
|
|
@@ -436,7 +463,7 @@ seismic, the recorder from the office, reports, the signed dossier and the
|
|
|
436
463
|
Reader, users and HTTPS, backups and the gate, new versions from inside
|
|
437
464
|
the program, GEA-VPN - and the pad attendant's after: the box and its
|
|
438
465
|
parts, installing the recorder on the Pi, the monitor, the USB mirror and
|
|
439
|
-
joining the VPN. Each lesson names who it is for, the page it is done on
|
|
466
|
+
joining the VPN - and GEA Driller from the office and on the rig PC. Each lesson names who it is for, the page it is done on
|
|
440
467
|
(a button opens it), how long it takes, the numbered steps with the
|
|
441
468
|
buttons as the page names them, and how you know it worked; each account
|
|
442
469
|
ticks lessons off. **Print the handout** gives the whole course as one
|
|
@@ -761,7 +788,7 @@ unsigned, the key hand-overs - and shows the reports as they were signed. A
|
|
|
761
788
|
reader made from the workspace knows the site's key fingerprints, so it
|
|
762
789
|
says whether a dossier is the site's; it allows no network request, and it
|
|
763
790
|
leaves the trusted time-stamp to `verify_dossier.py`. For a client who wants
|
|
764
|
-
it installed, every release also carries `GEA-Reader-Setup-0.
|
|
791
|
+
it installed, every release also carries `GEA-Reader-Setup-0.77.0.exe`: GEA
|
|
765
792
|
Reader as a Windows program of its own - its own icon and taskbar button,
|
|
766
793
|
Check with GEA Reader on a dossier's right-click menu, fingerprints the client
|
|
767
794
|
saves kept on that computer, nothing of GEA-Program. `gea help reader`.
|
|
@@ -1526,7 +1553,7 @@ attaches the zips to the GitHub release of that tag.
|
|
|
1526
1553
|
|
|
1527
1554
|
### The Windows installer
|
|
1528
1555
|
|
|
1529
|
-
Every release also carries `GEA-Program-Setup-0.
|
|
1556
|
+
Every release also carries `GEA-Program-Setup-0.77.0.exe` (for 0.77.0): the
|
|
1530
1557
|
same Windows kit installed like any Windows program, for the signed-in user
|
|
1531
1558
|
alone and with no administrator rights (`%LOCALAPPDATA%\Programs\GEA-Program`).
|
|
1532
1559
|
It asks for the site workspace (an existing one such as `C:\site` is used as
|
|
@@ -1545,7 +1572,7 @@ it, removes the program and leaves the workspace. Silent, for a site's
|
|
|
1545
1572
|
software deployment:
|
|
1546
1573
|
|
|
1547
1574
|
```
|
|
1548
|
-
GEA-Program-Setup-0.
|
|
1575
|
+
GEA-Program-Setup-0.77.0.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /WORKSPACE="C:\site" /SITENAME="Pad 3" /TASKS="desktopicon"
|
|
1549
1576
|
```
|
|
1550
1577
|
|
|
1551
1578
|
The setup is built by Inno Setup 6 from `tools/installer.iss` in the same
|
|
@@ -370,7 +370,7 @@ def main(argv=None) -> int:
|
|
|
370
370
|
p_ws.add_argument("--path", type=str, required=True, help="the workspace folder")
|
|
371
371
|
p_ws.add_argument("--action", type=str, default="list",
|
|
372
372
|
choices=["init", "add-file", "add-catalog", "add-live", "remove", "list", "migrate", "refresh", "audit",
|
|
373
|
-
"add-seismic", "refresh-seismic", "remove-seismic", "sar-film", "bit-image", "field-pull", "refresh-all", "add-track", "refresh-track", "remove-track",
|
|
373
|
+
"add-seismic", "refresh-seismic", "remove-seismic", "sar-film", "bit-image", "field-pull", "driller-pull", "refresh-all", "add-track", "refresh-track", "remove-track",
|
|
374
374
|
"seismic-dataset", "seismic-field", "add-site", "sites", "site-report", "remove-site", "rename",
|
|
375
375
|
"set-well", "sra-define", "sra-report", "associate", "osdu-export", "quakeml-export", "well-identity", "vibration-report",
|
|
376
376
|
"add-live-station", "live-fold", "live-run", "month-end", "add-layer", "layers", "remove-layer", "structure", "interval",
|
|
@@ -428,7 +428,7 @@ def main(argv=None) -> int:
|
|
|
428
428
|
p_ws.add_argument("--truth", type=str, default=None, help="add-track: ground truth CSV (point_id, lat, lon, utc[, note])")
|
|
429
429
|
p_ws.add_argument("--track", type=str, default=None, help="refresh-track / remove-track: the track id")
|
|
430
430
|
p_ws.add_argument("--win", type=float, default=600.0, help="add-track: the window length, s (default 600)")
|
|
431
|
-
p_ws.add_argument("--box", type=str, default=None, help="field-pull: the recorder's address (http://192.168.1.50:8780, as its page shows) or its mirror folder")
|
|
431
|
+
p_ws.add_argument("--box", type=str, default=None, help="field-pull: the recorder's address (http://192.168.1.50:8780, as its page shows) or its mirror folder; driller-pull: the rig PC's address (http://192.168.1.60:8790)")
|
|
432
432
|
p_ws.add_argument("--n-stations", type=int, default=24, help="bit-image: ground stations, the reference among them")
|
|
433
433
|
p_ws.add_argument("--radius", type=float, default=6000.0, help="bit-image: the array's outer ring, ft")
|
|
434
434
|
p_ws.add_argument("--noise", type=float, default=1.0, help="bit-image: ground noise against a reference arrival of 50")
|
|
@@ -1039,7 +1039,7 @@ def main(argv=None) -> int:
|
|
|
1039
1039
|
p_vp.add_argument("--subnet", type=str, default=None, help="with --create: the private subnet (default 10.77.0.0/24)")
|
|
1040
1040
|
p_vp.add_argument("--hub", type=str, default=None, metavar="HOST", help="change the hub's public name or address; every configuration is written again")
|
|
1041
1041
|
p_vp.add_argument("--add", type=str, default=None, metavar="NAME", help="add a member of this name (Pad 3 box) of the --kind")
|
|
1042
|
-
p_vp.add_argument("--kind", type=str, default="box", help="with --add: office, box, operator, reader or other (default box)")
|
|
1042
|
+
p_vp.add_argument("--kind", type=str, default="box", help="with --add: office, box, driller, operator, reader or other (default box)")
|
|
1043
1043
|
p_vp.add_argument("--remove", type=str, default=None, metavar="ID", help="remove the member of this id (pad-3-box); run the hub installer again after")
|
|
1044
1044
|
p_vp.add_argument("--bundles", action="store_true", help="write the hub installer and every member's configuration again")
|
|
1045
1045
|
p_vp.add_argument("--json", action="store_true")
|
|
@@ -3563,6 +3563,19 @@ def main(argv=None) -> int:
|
|
|
3563
3563
|
if not a.track:
|
|
3564
3564
|
raise SystemExit("remove-track needs --track TRACK_ID")
|
|
3565
3565
|
ws.remove_track(a.track, actor=a.actor); print("removed (folder kept):", a.track); return 0
|
|
3566
|
+
elif a.action == "driller-pull":
|
|
3567
|
+
from . import driller_link as DL
|
|
3568
|
+
if not a.box or not a.well:
|
|
3569
|
+
raise SystemExit("driller-pull needs --box http://192.168.1.60:8790 (the rig PC, or the folder of its records) and --well SWD-1")
|
|
3570
|
+
try:
|
|
3571
|
+
r = DL.pull(ws, a.box, a.well, actor=a.actor)
|
|
3572
|
+
except ValueError as e:
|
|
3573
|
+
raise SystemExit(f"driller-pull: {e}")
|
|
3574
|
+
sm = r['summary']
|
|
3575
|
+
print(f"driller-pull: {r['source']} ({r['rig_well']}) into {r['well']}: {len(r['fetched'])} file(s) fetched, {len(r['kept'])} already here, {len(r['bad'])} failed their hash; "
|
|
3576
|
+
f"{sm['decisions']} decisions ({sm['answers']['accept']} accepted, {sm['answers']['reject']} rejected, {sm['answers']['override']} done otherwise), "
|
|
3577
|
+
f"{sm['armed_sections']} armed section(s), {sm['commands']} command(s), {sm['commands_sent']} sent")
|
|
3578
|
+
return 0 if not r['bad'] else 1
|
|
3566
3579
|
elif a.action == "field-pull":
|
|
3567
3580
|
from . import field_pull as FP
|
|
3568
3581
|
if not a.box:
|
|
@@ -15243,7 +15243,7 @@ def section_do_reader_program(tmp: str) -> None:
|
|
|
15243
15243
|
marks = _re.findall(r'attach-kit\.sh "[^"]*" "[^"]+" "([^"]+)"', wf)
|
|
15244
15244
|
v = __version__
|
|
15245
15245
|
assets = [f"gea-program-{v}-win64.zip", f"GEA-Program-Setup-{v}.exe", f"gea-program-{v}-linux-x86_64.zip", f"GEA-Reader-Setup-{v}.exe", f"GEA-Reader-portable-{v}.zip",
|
|
15246
|
-
f"GEA-Recorder-{v}.tar.gz"]
|
|
15246
|
+
f"GEA-Recorder-{v}.tar.gz", f"GEA-Driller-{v}.tar.gz"]
|
|
15247
15247
|
app_id = _re.search(r"AppId=\{\{([0-9A-F-]+)\}", iss)
|
|
15248
15248
|
c3 = {
|
|
15249
15249
|
"kit": {"GEA-Reader.html", "GEA-Reader.cmd", "README.txt", "MANIFEST.json", "SHA256SUMS.txt", "reader.ico", "app/gea_reader.py", "app/winident.py",
|
|
@@ -15263,7 +15263,7 @@ def section_do_reader_program(tmp: str) -> None:
|
|
|
15263
15263
|
and '-m gea_reader ""%1""' in iss,
|
|
15264
15264
|
"workflow": "windows-reader:" in wf and "tools/build_reader.py" in wf and "tools\\reader_installer.iss" in wf and "-m gea_reader --selftest" in wf
|
|
15265
15265
|
and "the right-click entry is still there" in wf
|
|
15266
|
-
and all(sum(mk in a_ for mk in marks) == 1 for a_ in assets) and len(marks) ==
|
|
15266
|
+
and all(sum(mk in a_ for mk in marks) == 1 for a_ in assets) and len(marks) == 7,
|
|
15267
15267
|
}
|
|
15268
15268
|
failed3 = [k for k, v_ in c3.items() if not v_]
|
|
15269
15269
|
ok(not failed3,
|
|
@@ -15949,7 +15949,7 @@ def section_ds_updates(tmp: str) -> None:
|
|
|
15949
15949
|
pkg = Path(__file__).parent
|
|
15950
15950
|
d = Path(tmp, "ds"); d.mkdir()
|
|
15951
15951
|
ws = Workspace.create(str(d / "ws"), "Pad 3 up", actor="tester")
|
|
15952
|
-
blobs = {"GEA-Program-Setup-9.9.9.exe": os.urandom(40000), "GEA-Reader-Setup-9.9.9.exe": os.urandom(6000), "GEA-Recorder-9.9.9.tar.gz": os.urandom(2000),
|
|
15952
|
+
blobs = {"GEA-Program-Setup-9.9.9.exe": os.urandom(40000), "GEA-Reader-Setup-9.9.9.exe": os.urandom(6000), "GEA-Recorder-9.9.9.tar.gz": os.urandom(2000), "GEA-Driller-9.9.9.tar.gz": os.urandom(2500),
|
|
15953
15953
|
"gea-program-9.9.9-win64.zip": os.urandom(500)}
|
|
15954
15954
|
state = {"port": 0}
|
|
15955
15955
|
|
|
@@ -15989,14 +15989,14 @@ def section_ds_updates(tmp: str) -> None:
|
|
|
15989
15989
|
rec2 = UP.fetch_kits(ws, "tester", release=rel, fetch=fetch)
|
|
15990
15990
|
on = UP.on_hand(ws)
|
|
15991
15991
|
c1 = {
|
|
15992
|
-
"release": rel["version"] == "9.9.9" and [a["kit"] for a in rel["assets"]] == ["GEA-Program-Setup-", "GEA-Reader-Setup-", "GEA-Recorder-"] and all(a["sha256"] for a in rel["assets"]),
|
|
15992
|
+
"release": rel["version"] == "9.9.9" and [a["kit"] for a in rel["assets"]] == ["GEA-Program-Setup-", "GEA-Reader-Setup-", "GEA-Recorder-", "GEA-Driller-"] and all(a["sha256"] for a in rel["assets"]),
|
|
15993
15993
|
"unreachable": down.get("error") and down["version"] is None,
|
|
15994
|
-
"fetched": all(f["verified"] and f["fetched"] for f in rec["files"]) and len(rec["files"]) ==
|
|
15994
|
+
"fetched": all(f["verified"] and f["fetched"] for f in rec["files"]) and len(rec["files"]) == 4 and rec["moved_aside"] == ["GEA-Program-Setup-0.1.0.exe"]
|
|
15995
15995
|
and Path(inst, "_older", "GEA-Program-Setup-0.1.0.exe").is_file() and all(Path(inst, f["name"]).read_bytes() == blobs[f["name"]] for f in rec["files"] if f["name"] != "GEA-Reader-Setup-9.9.9.exe"),
|
|
15996
15996
|
"state": st["state"] == "behind" and all(st["newest_on_hand"].values()) and st_cur["state"] == "current" and st["last_fetch"]["version"] == "9.9.9",
|
|
15997
15997
|
"tampered": [f["name"] for f in rec2["files"] if f.get("rejected")] == ["GEA-Reader-Setup-9.9.9.exe"] and not Path(inst, "GEA-Reader-Setup-9.9.9.exe").exists()
|
|
15998
|
-
and [f["name"] for f in rec2["files"] if f["verified"] and not f["fetched"]] == ["GEA-Program-Setup-9.9.9.exe", "GEA-Recorder-9.9.9.tar.gz"],
|
|
15999
|
-
"on_hand": {h["name"]: h["verified"] for h in on} == {"GEA-Program-Setup-9.9.9.exe": True, "GEA-Recorder-9.9.9.tar.gz": True},
|
|
15998
|
+
and [f["name"] for f in rec2["files"] if f["verified"] and not f["fetched"]] == ["GEA-Program-Setup-9.9.9.exe", "GEA-Recorder-9.9.9.tar.gz", "GEA-Driller-9.9.9.tar.gz"],
|
|
15999
|
+
"on_hand": {h["name"]: h["verified"] for h in on} == {"GEA-Driller-9.9.9.tar.gz": True, "GEA-Program-Setup-9.9.9.exe": True, "GEA-Recorder-9.9.9.tar.gz": True},
|
|
16000
16000
|
"audit": "update.fetch" in [a["action"] for a in ws.audit_log(20)],
|
|
16001
16001
|
}
|
|
16002
16002
|
failed1 = [k for k, v in c1.items() if not v]
|
|
@@ -16327,9 +16327,9 @@ def section_du_tutorial(tmp: str) -> None:
|
|
|
16327
16327
|
"contract": not bad_contract,
|
|
16328
16328
|
"pages_exist": not bad_where,
|
|
16329
16329
|
"both_audiences": {l["who"] for l in ls} == {"office", "pad"} and sum(1 for l in ls if l["who"] == "pad") >= 3,
|
|
16330
|
-
"parts": parts_cover and len(TU.PARTS) ==
|
|
16330
|
+
"parts": parts_cover and len(TU.PARTS) == 9,
|
|
16331
16331
|
"buttons_known": not unknown_buttons,
|
|
16332
|
-
"every_program": all(any(w in (l["title"] + " " + l["summary"]).lower() for l in ls) for w in ("install", "reader", "recorder", "vpn", "dossier", "patch", "backup")),
|
|
16332
|
+
"every_program": all(any(w in (l["title"] + " " + l["summary"]).lower() for l in ls) for w in ("install", "reader", "recorder", "vpn", "dossier", "patch", "backup", "driller")),
|
|
16333
16333
|
}
|
|
16334
16334
|
failed1 = [k for k, v in c1.items() if not v]
|
|
16335
16335
|
ok(not failed1,
|
|
@@ -16409,6 +16409,270 @@ def section_du_tutorial(tmp: str) -> None:
|
|
|
16409
16409
|
"it; numbered steps render as a list" + (f" [failed: {', '.join(failed2)}]" if failed2 else ""))
|
|
16410
16410
|
|
|
16411
16411
|
|
|
16412
|
+
def section_dv_driller(tmp: str) -> None:
|
|
16413
|
+
"""Section DV - GEA Driller: the twin's arithmetic (a seed repeats, building turns the bit up, circulating cleans
|
|
16414
|
+
without footage, the limits penalize, a filled hole sticks the pipe), the policy's gradients against finite
|
|
16415
|
+
differences, the shipped policy against the textbook driller on held-out scenes and a short training that
|
|
16416
|
+
learns; the service with the twin as the rig - a decision from the feed, the operator's answers with a name,
|
|
16417
|
+
the records with their hashes, the closed loop armed by name, commanding through the null downlink that sends
|
|
16418
|
+
nothing, disarmed by a crossed limit and by the section's end, refused when not allowed; GEA's pull of the
|
|
16419
|
+
records with a tampered file refused, the summary, the routes, the card, the command, the kit and the help."""
|
|
16420
|
+
import http.cookiejar
|
|
16421
|
+
import importlib
|
|
16422
|
+
import urllib.error
|
|
16423
|
+
import urllib.request
|
|
16424
|
+
from . import __version__
|
|
16425
|
+
from . import driller_link as DL
|
|
16426
|
+
from . import helplib as H
|
|
16427
|
+
from .service import Service, Users
|
|
16428
|
+
from .workspace import Workspace
|
|
16429
|
+
pkg = Path(__file__).parent
|
|
16430
|
+
d = Path(tmp, "dv"); d.mkdir()
|
|
16431
|
+
prog = DL.program()
|
|
16432
|
+
if prog is None:
|
|
16433
|
+
ok(True, "DV the driller's program (gea-driller) is not installed beside GEA in this install; the kit and the setup carry it - nothing to check here")
|
|
16434
|
+
return
|
|
16435
|
+
if prog["env"] and prog["env"] not in sys.path:
|
|
16436
|
+
sys.path.insert(0, prog["env"])
|
|
16437
|
+
T = importlib.import_module("gea_driller.twin"); P = importlib.import_module("gea_driller.policy"); A = importlib.import_module("gea_driller.advisor")
|
|
16438
|
+
C = importlib.import_module("gea_driller.config"); S = importlib.import_module("gea_driller.service")
|
|
16439
|
+
np_ = importlib.import_module("numpy")
|
|
16440
|
+
# -- DV1 the twin ------------------------------------------------------------------------------------------------------
|
|
16441
|
+
r1 = T.run_episode(T.Lateral(T.Scene(0)), T.textbook_action); r2 = T.run_episode(T.Lateral(T.Scene(0)), T.textbook_action)
|
|
16442
|
+
lb = T.Lateral(T.Scene(3)); lb.reset(); lh = T.Lateral(T.Scene(3)); lh.reset()
|
|
16443
|
+
for _ in range(8):
|
|
16444
|
+
lb.step((4, 1, 1, 1, 0)); lh.step((2, 1, 1, 1, 0))
|
|
16445
|
+
lc = T.Lateral(T.Scene(3)); lc.reset(); lc.bed = 0.6; o_, rc, _, ic = lc.step((2, 1, 1, 1, 1))
|
|
16446
|
+
lw = T.Lateral(T.Scene(3)); lw.reset(); lw.bed = 0.05; _, rw, _, _ = lw.step((2, 1, 1, 1, 1)) # conditioning a clean hole costs more
|
|
16447
|
+
# a hole left to fill sticks the pipe, sooner or later, under heavy weight and little flow
|
|
16448
|
+
stuck = 0
|
|
16449
|
+
for sd in range(8):
|
|
16450
|
+
l_ = T.Lateral(T.Scene(100 + sd)); l_.reset(); l_.bed = 0.9
|
|
16451
|
+
while not l_.done and l_.steps < 80:
|
|
16452
|
+
l_.step((2, 2, 0, 0, 0))
|
|
16453
|
+
stuck += 1 if l_.ended == "stuck pipe" else 0
|
|
16454
|
+
# the vibration limit: heavy weight at slow rotation in the shale above costs reward
|
|
16455
|
+
lv = T.Lateral(T.Scene(5)); lv.reset(); lv.tvd = lv.scene.layer_top(0.0) - 15.0
|
|
16456
|
+
_, r_heavy, _, i_heavy = lv.step((2, 2, 0, 1, 0))
|
|
16457
|
+
c1 = {
|
|
16458
|
+
"repeats": abs(r1["reward"] - r2["reward"]) < 1e-9 and r1["footage_ft"] == r2["footage_ft"],
|
|
16459
|
+
"builds": lb.incl > lh.incl + 1.5 and lb.tvd < lh.tvd,
|
|
16460
|
+
"conditioning": lc.bed < 0.6 and lc.footage == 0.0 and rc > rw,
|
|
16461
|
+
"stuck": stuck >= 6,
|
|
16462
|
+
"vibration": i_heavy["vibration"] > T.VIB_LIMIT and r_heavy < 0,
|
|
16463
|
+
"obs": len(T.OBS_NAMES) == T.OBS_SIZE == lb.observe().shape[0] and all(np_.isfinite(lb.observe())),
|
|
16464
|
+
"scene_random": T.Scene(1).thickness != T.Scene(2).thickness and T.Scene(1).describe()["seed"] == 1,
|
|
16465
|
+
}
|
|
16466
|
+
failed1 = [k for k, v in c1.items() if not v]
|
|
16467
|
+
ok(not failed1,
|
|
16468
|
+
"DV1 the twin repeats itself for a seed, building turns the bit upward against holding, conditioning takes no footage and is cheap only when the "
|
|
16469
|
+
"hole needs it, a hole left to fill under heavy weight and little flow sticks the pipe, heavy weight at slow rotation in the shale costs the "
|
|
16470
|
+
"vibration limit, the observation is finite and named, and scenes differ by seed" + (f" [failed: {', '.join(failed1)}]" if failed1 else ""))
|
|
16471
|
+
# -- DV2 the policy ------------------------------------------------------------------------------------------------------
|
|
16472
|
+
pol0 = P.Policy(seed=1)
|
|
16473
|
+
lat = T.Lateral(T.Scene(5)); o = lat.reset(); obs = []; acts = []
|
|
16474
|
+
rr = np_.random.RandomState(0)
|
|
16475
|
+
for _ in range(30):
|
|
16476
|
+
a, lp, v = pol0.act(o, rr); obs.append(o); acts.append(a); o, _, dn, _ = lat.step(a)
|
|
16477
|
+
if dn:
|
|
16478
|
+
o = lat.reset()
|
|
16479
|
+
obs = np_.array(obs); acts = np_.array(acts)
|
|
16480
|
+
old = np_.array([pol0.act(ob, rr)[1] for ob in obs]); adv = rr.normal(size=30); ret = rr.normal(size=30)
|
|
16481
|
+
|
|
16482
|
+
def loss_of(pol):
|
|
16483
|
+
logits, v, _, _ = pol.forward(obs); logp = np_.zeros(30); ent = np_.zeros(30)
|
|
16484
|
+
for hi, sl in enumerate(P.HEAD_SLICES):
|
|
16485
|
+
p_ = P._softmax(logits[:, sl]); logp += np_.log(p_[np_.arange(30), acts[:, hi]]); ent += -(p_ * np_.log(p_)).sum(1)
|
|
16486
|
+
ratio = np_.exp(logp - old)
|
|
16487
|
+
return -np_.mean(np_.minimum(ratio * adv, np_.clip(ratio, 0.8, 1.2) * adv)) + 0.5 * 0.5 * np_.mean((v - ret) ** 2) - 0.01 * ent.mean()
|
|
16488
|
+
g, _ = P._loss_and_grads(pol0, obs, acts, old, adv, ret, 0.2, 0.5, 0.01)
|
|
16489
|
+
grads_ok = True
|
|
16490
|
+
for k in ("W1", "W2", "W3", "b1", "b3"):
|
|
16491
|
+
i = tuple(0 for _ in pol0.p[k].shape); eps = 1e-6
|
|
16492
|
+
pol0.p[k][i] += eps; lp_ = loss_of(pol0); pol0.p[k][i] -= 2 * eps; lm_ = loss_of(pol0); pol0.p[k][i] += eps
|
|
16493
|
+
num = (lp_ - lm_) / (2 * eps)
|
|
16494
|
+
grads_ok = grads_ok and abs(num - g[k][i]) <= 1e-5 * max(1.0, abs(num))
|
|
16495
|
+
shipped = P.Policy.load(S.SHIPPED_POLICY)
|
|
16496
|
+
ev = P.evaluate(P.policy_act_fn(shipped), range(20), "agent"); tb = P.evaluate(T.textbook_action, range(20), "textbook")
|
|
16497
|
+
fresh = P.Policy(seed=5); before = P.evaluate(P.policy_act_fn(fresh), range(10, 14), "fresh")
|
|
16498
|
+
P.train(fresh, seconds=10.0, batch_steps=2048, n_envs=8, scene_seed0=600000)
|
|
16499
|
+
after = P.evaluate(P.policy_act_fn(fresh), range(10, 14), "trained")
|
|
16500
|
+
rt = P.Policy.from_json(shipped.to_json())
|
|
16501
|
+
same = all(np_.allclose(rt.p[k], shipped.p[k]) for k in shipped.p)
|
|
16502
|
+
try:
|
|
16503
|
+
bad = shipped.to_json(); bad["action_sizes"] = [1]; P.Policy.from_json(bad); layout_refused = False
|
|
16504
|
+
except ValueError:
|
|
16505
|
+
layout_refused = True
|
|
16506
|
+
ex = shipped.explain(T.Lateral(T.Scene(2)).reset())
|
|
16507
|
+
c2 = {
|
|
16508
|
+
"gradients": grads_ok,
|
|
16509
|
+
"beats_textbook": ev["reward"] > tb["reward"] and ev["in_layer_pct"] > tb["in_layer_pct"] + 10.0 and ev["stuck"] <= tb["stuck"],
|
|
16510
|
+
"learns": after["reward"] > before["reward"],
|
|
16511
|
+
"file": same and layout_refused and int(shipped.meta.get("trained_steps", 0)) >= 1000000,
|
|
16512
|
+
"explains": set(ex["choices"]) == set(T.ACTION_NAMES) and all(0 < c["confidence"] <= 1 for c in ex["choices"].values()) and ex["choices"]["wob"]["choice"] in T.WOB_CHOICES,
|
|
16513
|
+
}
|
|
16514
|
+
failed2 = [k for k, v in c2.items() if not v]
|
|
16515
|
+
ok(not failed2,
|
|
16516
|
+
f"DV2 the policy's written-out gradients agree with finite differences; the shipped policy ({int(shipped.meta.get('trained_steps', 0)):,} twin steps) beats the "
|
|
16517
|
+
f"textbook driller on twenty held-out scenes (in the layer {ev['in_layer_pct']:.0f}% against {tb['in_layer_pct']:.0f}%, reward {ev['reward']:.0f} against {tb['reward']:.0f}, "
|
|
16518
|
+
"SIMULATION); ten seconds of training raise a fresh policy's return; the file round-trips and another layout is refused; a decision explains itself in "
|
|
16519
|
+
"operational units with a confidence per choice" + (f" [failed: {', '.join(failed2)}]" if failed2 else ""))
|
|
16520
|
+
# -- DV3 the service with the twin as the rig ------------------------------------------------------------------------
|
|
16521
|
+
cfg = json.loads(json.dumps(C.EXAMPLE)); cfg["output"]["dir"] = str(d / "rig"); cfg["status"]["port"] = 0; cfg["status"]["bind"] = "127.0.0.1"
|
|
16522
|
+
cfg["rig"]["transport"] = "sim"; cfg["closed_loop"]["allowed"] = True; cfg["closed_loop"]["stale_s"] = 30; cfg["limits"]["vibration_index"] = 1.2
|
|
16523
|
+
cfg = C.check(cfg)
|
|
16524
|
+
try:
|
|
16525
|
+
C.check(json.loads(json.dumps(cfg)) | {"closed_loop": {"allowed": True, "downlink": "acme"}}); cfg_refused = False
|
|
16526
|
+
except C.ConfigError:
|
|
16527
|
+
cfg_refused = True
|
|
16528
|
+
drl = S.Driller(cfg, policy=shipped, twin_seed=11, twin_pace_s=0.6)
|
|
16529
|
+
drl.start()
|
|
16530
|
+
try:
|
|
16531
|
+
t_end = time.monotonic() + 20
|
|
16532
|
+
while time.monotonic() < t_end and not drl.advisor.current:
|
|
16533
|
+
time.sleep(0.2)
|
|
16534
|
+
cur = dict(drl.advisor.current) if drl.advisor.current else None
|
|
16535
|
+
|
|
16536
|
+
def call(path, body):
|
|
16537
|
+
rq = urllib.request.Request(drl.url + path, data=json.dumps(body).encode(), headers={"Content-Type": "application/json"}, method="POST")
|
|
16538
|
+
try:
|
|
16539
|
+
with urllib.request.urlopen(rq, timeout=5) as r_:
|
|
16540
|
+
return r_.status, json.load(r_)
|
|
16541
|
+
except urllib.error.HTTPError as e:
|
|
16542
|
+
return e.code, json.loads(e.read() or b"{}")
|
|
16543
|
+
s_noname, _ = call("/api/answer", {"what": "accept", "by": ""})
|
|
16544
|
+
s_acc, _ = call("/api/answer", {"what": "accept", "by": "tester"})
|
|
16545
|
+
s_twice, _ = call("/api/answer", {"what": "accept", "by": "tester"})
|
|
16546
|
+
time.sleep(1.5)
|
|
16547
|
+
s_ov, _ = call("/api/answer", {"what": "override", "by": "tester", "note": "held", "override": {"build_deg_100ft": 0.0, "wob_klb": 25}})
|
|
16548
|
+
md = drl.feed.snapshot()["state"]["hole_depth"]
|
|
16549
|
+
s_long, _ = call("/api/arm", {"by": "tester", "to_md": md + 5000})
|
|
16550
|
+
s_arm, armed = call("/api/arm", {"by": "tester", "to_md": md + 150})
|
|
16551
|
+
t_end = time.monotonic() + 30
|
|
16552
|
+
while time.monotonic() < t_end and drl.advisor.armed is not None:
|
|
16553
|
+
time.sleep(0.3)
|
|
16554
|
+
ended_by_section = drl.advisor.arm_log[-1]["event"] == "disarmed" and "drilled" in drl.advisor.arm_log[-1]["reason"]
|
|
16555
|
+
# a crossed limit disarms it at once
|
|
16556
|
+
md = drl.feed.snapshot()["state"]["hole_depth"]
|
|
16557
|
+
s_arm2, _ = call("/api/arm", {"by": "tester", "to_md": md + 400})
|
|
16558
|
+
drl.cfg["limits"]["vibration_index"] = 0.01 # the limit lowered under the running loop: the next look disarms it
|
|
16559
|
+
t_end = time.monotonic() + 8
|
|
16560
|
+
while time.monotonic() < t_end and drl.advisor.armed is not None:
|
|
16561
|
+
time.sleep(0.2)
|
|
16562
|
+
drl.cfg["limits"]["vibration_index"] = 1.2
|
|
16563
|
+
ended_by_limit = drl.advisor.arm_log[-1]["event"] == "disarmed" and "vibration" in drl.advisor.arm_log[-1]["reason"]
|
|
16564
|
+
with urllib.request.urlopen(drl.url + "/live.json", timeout=5) as r_:
|
|
16565
|
+
live = json.load(r_)
|
|
16566
|
+
with urllib.request.urlopen(drl.url + "/live", timeout=5) as r_:
|
|
16567
|
+
screen = r_.read().decode("utf-8")
|
|
16568
|
+
with urllib.request.urlopen(drl.url + "/health", timeout=5) as r_:
|
|
16569
|
+
health = json.load(r_)
|
|
16570
|
+
s_404 = urllib.request.urlopen(urllib.request.Request(drl.url + "/files/../config.json"), timeout=5) if False else None
|
|
16571
|
+
try:
|
|
16572
|
+
urllib.request.urlopen(drl.url + "/files/../../etc/passwd", timeout=5); traversal = False
|
|
16573
|
+
except urllib.error.HTTPError as e:
|
|
16574
|
+
traversal = e.code == 404
|
|
16575
|
+
finally:
|
|
16576
|
+
drl.stop()
|
|
16577
|
+
cmds = [json.loads(l) for l in open(d / "rig" / "commands.jsonl", encoding="utf-8")]
|
|
16578
|
+
decs = [json.loads(l) for l in open(d / "rig" / "decisions.jsonl", encoding="utf-8")]
|
|
16579
|
+
man = json.load(open(d / "rig" / "manifest.json", encoding="utf-8"))
|
|
16580
|
+
# advisory only: arming refused when the config does not allow it
|
|
16581
|
+
cfg2 = json.loads(json.dumps(cfg)); cfg2["output"]["dir"] = str(d / "rig2"); cfg2["closed_loop"]["allowed"] = False
|
|
16582
|
+
drl2 = S.Driller(C.check(cfg2), policy=shipped, twin_seed=12, twin_pace_s=1.0)
|
|
16583
|
+
try:
|
|
16584
|
+
arm_refused = False
|
|
16585
|
+
try:
|
|
16586
|
+
drl2.advisor.arm("tester", 10200.0, 10300.0)
|
|
16587
|
+
except ValueError as e:
|
|
16588
|
+
arm_refused = "not allowed" in str(e)
|
|
16589
|
+
finally:
|
|
16590
|
+
drl2.stop()
|
|
16591
|
+
c3 = {
|
|
16592
|
+
"decision": cur is not None and cur["recommend"]["words"] and cur["recommend"]["wob_klb"] in T.WOB_CHOICES and len(cur["reasons"]) >= 2 and cur["recommend"]["conditioning"] in T.COND_CHOICES,
|
|
16593
|
+
"answers": s_noname == 400 and s_acc == 200 and s_twice == 400 and s_ov == 200 and any((x.get("answer") or {}).get("what") == "override" and x["answer"]["by"] == "tester" for x in decs),
|
|
16594
|
+
"armed": s_long == 400 and s_arm == 200 and armed.get("ok") and s_arm2 == 200 and any(c["event"] == "command" and c["result"]["sent"] is False and c["by"] == "tester" for c in cmds),
|
|
16595
|
+
"disarmed": ended_by_section and ended_by_limit and cmds[-1]["event"] == "disarmed",
|
|
16596
|
+
"refusals": cfg_refused and arm_refused,
|
|
16597
|
+
"screen": live["ok"] and live["twin"]["label"] == "SIMULATION" and "Arm for this section" in screen and "Did something else" in screen and health["program"] == "GEA Driller" and traversal,
|
|
16598
|
+
"manifest": {"decisions.jsonl", "commands.jsonl", "surveys.csv"} <= {f["file"] for f in man["files"]} and all(f["sha256"] for f in man["files"]) and man["program"] == "GEA Driller",
|
|
16599
|
+
}
|
|
16600
|
+
failed3 = [k for k, v in c3.items() if not v]
|
|
16601
|
+
ok(not failed3,
|
|
16602
|
+
"DV3 with the twin as the rig the service makes a decision from the feed in the driller's units with its reasons; answers need a name and come once; "
|
|
16603
|
+
"a section longer than allowed is refused, an armed section's decisions go to the null downlink as commands with the operator's name and nothing sent, "
|
|
16604
|
+
"and the loop disarms itself at the section's end and at a crossed vibration limit; a downlink that does not exist and arming when the config forbids it "
|
|
16605
|
+
"are refused; the screen carries the switch and the answers, the file route refuses a path outside the folder; the manifest names every record with its hash"
|
|
16606
|
+
+ (f" [failed: {', '.join(failed3)}]" if failed3 else ""))
|
|
16607
|
+
# -- DV4 GEA's side: the pull, the twin on this computer, the routes, the card, the command, the kit, the help --------------
|
|
16608
|
+
ws = Workspace.create(str(d / "ws"), "Pad 3 driller", actor="tester")
|
|
16609
|
+
w = ws.add_well_records("Pad 3 H-1", actor="tester")
|
|
16610
|
+
r1_ = DL.pull(ws, str(d / "rig"), w["id"], actor="tester")
|
|
16611
|
+
r2_ = DL.pull(ws, str(d / "rig"), w["id"], actor="tester")
|
|
16612
|
+
with open(d / "rig" / "decisions.jsonl", "a", encoding="utf-8") as f:
|
|
16613
|
+
f.write('{"tampered": true}\n')
|
|
16614
|
+
os.remove(Path(ws.path, "wells", w["id"], "driller", "decisions.jsonl")) # the copy here gone, the altered one is fetched and refused
|
|
16615
|
+
r3_ = DL.pull(ws, str(d / "rig"), w["id"], actor="tester")
|
|
16616
|
+
sm = r1_["summary"]
|
|
16617
|
+
try:
|
|
16618
|
+
DL.pull(ws, str(d / "rig"), "no-such-well", actor="tester"); nowell = False
|
|
16619
|
+
except ValueError:
|
|
16620
|
+
nowell = True
|
|
16621
|
+
try:
|
|
16622
|
+
DL.pull(ws, str(d / "ws"), w["id"], actor="tester"); notdriller = False
|
|
16623
|
+
except (ValueError, OSError):
|
|
16624
|
+
notdriller = True
|
|
16625
|
+
Users(str(Path(ws.path, "users.json"))).add("op", "op-pass-123", "operator")
|
|
16626
|
+
svc = Service(ws.path, port=0, scheduler=False).start()
|
|
16627
|
+
base = svc.url.rstrip("/")
|
|
16628
|
+
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(http.cookiejar.CookieJar()))
|
|
16629
|
+
|
|
16630
|
+
def gcall(method, path, body=None):
|
|
16631
|
+
rq = urllib.request.Request(base + path, method=method, data=(json.dumps(body).encode() if body is not None else None))
|
|
16632
|
+
rq.add_header("Content-Type", "application/json"); rq.add_header("X-GEA-Action", "1")
|
|
16633
|
+
try:
|
|
16634
|
+
with opener.open(rq, timeout=60) as rr_:
|
|
16635
|
+
return rr_.status, json.loads(rr_.read())
|
|
16636
|
+
except urllib.error.HTTPError as e:
|
|
16637
|
+
return e.code, json.loads(e.read() or b"{}")
|
|
16638
|
+
try:
|
|
16639
|
+
s_anon, _ = gcall("GET", "/api/driller")
|
|
16640
|
+
gcall("POST", "/api/login", {"name": "op", "password": "op-pass-123"})
|
|
16641
|
+
s_d, dd = gcall("GET", "/api/driller")
|
|
16642
|
+
s_w, dw = gcall("GET", f"/api/driller/{w['id']}")
|
|
16643
|
+
s_bad, _ = gcall("POST", "/api/driller/pull", {"source": "", "well": w["id"]})
|
|
16644
|
+
s_job, job = gcall("POST", "/api/driller/pull", {"source": str(d / "rig"), "well": w["id"]})
|
|
16645
|
+
s_sim_bad, _ = gcall("POST", "/api/driller/sim/start", {"seed": -1})
|
|
16646
|
+
finally:
|
|
16647
|
+
svc.stop()
|
|
16648
|
+
app_src = (pkg / "web" / "app.html").read_text(encoding="utf-8")
|
|
16649
|
+
main_src = (pkg / "__main__.py").read_text(encoding="utf-8")
|
|
16650
|
+
wf = (pkg.parent / ".github" / "workflows" / "build-installer.yml").read_text(encoding="utf-8") if (pkg.parent / ".github" / "workflows" / "build-installer.yml").is_file() else None
|
|
16651
|
+
bi = (pkg.parent / "tools" / "build_installer.py").read_text(encoding="utf-8") if (pkg.parent / "tools" / "build_installer.py").is_file() else None
|
|
16652
|
+
from . import vpn as VP
|
|
16653
|
+
c4 = {
|
|
16654
|
+
"pull": set(r1_["fetched"]) == {"decisions.jsonl", "commands.jsonl", "surveys.csv"} and not r1_["bad"] and set(r2_["kept"]) == set(r1_["fetched"]) and not r2_["fetched"],
|
|
16655
|
+
"tampered": r3_["bad"] == ["decisions.jsonl"] and not Path(ws.path, "wells", w["id"], "driller", "decisions.jsonl").is_file() and Path(ws.path, "wells", w["id"], "driller", "commands.jsonl").is_file(),
|
|
16656
|
+
"summary": sm["decisions"] >= 3 and sm["answers"]["accept"] == 1 and sm["answers"]["override"] == 1 and sm["armed_sections"] == 2 and sm["commands"] >= 1 and sm["commands_sent"] == 0
|
|
16657
|
+
and sm["hole_under_advice_ft"] > 0 and sm["answered_by"].get("tester") == 2 and len(sm["last"]) >= 3 and len(sm["disarmed"]) == 2,
|
|
16658
|
+
"refusals": nowell and notdriller,
|
|
16659
|
+
"routes": s_anon in (401, 403) and s_d == 200 and len(dd["wells"]) == 1 and dd["sim"]["label"] == "SIMULATION" and s_w == 200 and dw["well"] == w["id"]
|
|
16660
|
+
and s_bad == 400 and s_job == 200 and "id" in job and s_sim_bad == 400,
|
|
16661
|
+
"audit": {"driller.pull"} <= {a["action"] for a in ws.audit_log()},
|
|
16662
|
+
"card": all(t_ in app_src for t_ in ("drillerCardHtml", "/api/driller/pull", "/api/driller/sim/start", "GEA Driller", "Start the twin as the rig", "Open the driller's screen")),
|
|
16663
|
+
"cli": '"driller-pull"' in main_src and "DL.pull" in main_src,
|
|
16664
|
+
"vpn": VP.KINDS.get("driller") and VP.PORTS.get("driller") == 8790,
|
|
16665
|
+
"kit": (wf is None or ("GEA-Driller-" in wf and "build_driller.py" in wf)) and (bi is None or "gea-driller=={version}" in bi) and (not (pkg.parent / "tools").is_dir() or (pkg.parent / "tools" / "build_driller.py").is_file()),
|
|
16666
|
+
"help": not H.check("driller") and any(t_ == "driller" for t_, _, _ in H.INDEX) and "GEA Driller" in (pkg / "help" / "IT_SECURITY.md").read_text(encoding="utf-8"),
|
|
16667
|
+
}
|
|
16668
|
+
failed4 = [k for k, v in c4.items() if not v]
|
|
16669
|
+
ok(not failed4,
|
|
16670
|
+
"DV4 GEA pulls the driller's records into the well checked against their hashes (a second pull fetches nothing; a file altered after its hash is "
|
|
16671
|
+
"named and not taken), summarizes the decisions, the answers by name, the armed sections and the commands; an unknown well and a folder that is not "
|
|
16672
|
+
"a driller's are refused; the routes (anonymous refused, a bad source 400, the pull as a job, a bad seed 400), the audit line, the Drill string "
|
|
16673
|
+
"card, the workspace command, the VPN kind, the kit and the workflow, and the help page carry it" + (f" [failed: {', '.join(failed4)}]" if failed4 else ""))
|
|
16674
|
+
|
|
16675
|
+
|
|
16412
16676
|
def main() -> int:
|
|
16413
16677
|
print("GEA-Program - ACCEPTANCE SUITE (the product gate)")
|
|
16414
16678
|
# a handle a job subprocess still holds at the end must not turn a finished gate into a traceback on Windows:
|
|
@@ -16537,6 +16801,7 @@ def main() -> int:
|
|
|
16537
16801
|
section_ds_updates(tmp)
|
|
16538
16802
|
section_dt_vpn(tmp)
|
|
16539
16803
|
section_du_tutorial(tmp)
|
|
16804
|
+
section_dv_driller(tmp)
|
|
16540
16805
|
if _FAILS:
|
|
16541
16806
|
print(f"[ACCEPTANCE] {len(_FAILS)} FAILURES ({_PASS} passed):")
|
|
16542
16807
|
for f in _FAILS:
|