gea-program 0.75.0__tar.gz → 0.76.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 (424) hide show
  1. {gea_program-0.75.0/gea_program.egg-info → gea_program-0.76.0}/PKG-INFO +24 -4
  2. {gea_program-0.75.0 → gea_program-0.76.0}/README.md +23 -3
  3. {gea_program-0.75.0 → gea_program-0.76.0}/gea/__init__.py +1 -1
  4. {gea_program-0.75.0 → gea_program-0.76.0}/gea/__main__.py +37 -0
  5. {gea_program-0.75.0 → gea_program-0.76.0}/gea/acceptance_tests.py +137 -5
  6. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/IT_SECURITY.md +5 -0
  7. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/install.md +2 -2
  8. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/reader.md +1 -1
  9. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/recorder.md +1 -1
  10. gea_program-0.76.0/gea/help/tutorial/01-install.md +26 -0
  11. gea_program-0.76.0/gea/help/tutorial/02-sign-in.md +22 -0
  12. gea_program-0.76.0/gea/help/tutorial/03-site.md +22 -0
  13. gea_program-0.76.0/gea/help/tutorial/04-add-well.md +24 -0
  14. gea_program-0.76.0/gea/help/tutorial/05-records.md +22 -0
  15. gea_program-0.76.0/gea/help/tutorial/06-well-page.md +19 -0
  16. gea_program-0.76.0/gea/help/tutorial/07-declare.md +20 -0
  17. gea_program-0.76.0/gea/help/tutorial/08-patches.md +22 -0
  18. gea_program-0.76.0/gea/help/tutorial/09-alarms.md +19 -0
  19. gea_program-0.76.0/gea/help/tutorial/10-control-room.md +17 -0
  20. gea_program-0.76.0/gea/help/tutorial/11-summary-month.md +17 -0
  21. gea_program-0.76.0/gea/help/tutorial/12-where-the-well-is.md +19 -0
  22. gea_program-0.76.0/gea/help/tutorial/13-drilling-pages.md +24 -0
  23. gea_program-0.76.0/gea/help/tutorial/14-production-pages.md +17 -0
  24. gea_program-0.76.0/gea/help/tutorial/15-seismic.md +19 -0
  25. gea_program-0.76.0/gea/help/tutorial/16-seismicity.md +18 -0
  26. gea_program-0.76.0/gea/help/tutorial/17-recorder-office.md +18 -0
  27. gea_program-0.76.0/gea/help/tutorial/18-reports.md +18 -0
  28. gea_program-0.76.0/gea/help/tutorial/19-dossier-reader.md +17 -0
  29. gea_program-0.76.0/gea/help/tutorial/20-admin.md +19 -0
  30. gea_program-0.76.0/gea/help/tutorial/21-upkeep.md +19 -0
  31. gea_program-0.76.0/gea/help/tutorial/22-updates.md +17 -0
  32. gea_program-0.76.0/gea/help/tutorial/23-vpn.md +22 -0
  33. gea_program-0.76.0/gea/help/tutorial/24-the-box.md +26 -0
  34. gea_program-0.76.0/gea/help/tutorial/25-install-recorder.md +21 -0
  35. gea_program-0.76.0/gea/help/tutorial/26-monitor.md +17 -0
  36. gea_program-0.76.0/gea/help/tutorial/27-mirror-vpn.md +21 -0
  37. gea_program-0.76.0/gea/help/tutorial.md +13 -0
  38. {gea_program-0.75.0 → gea_program-0.76.0}/gea/helplib.py +12 -7
  39. {gea_program-0.75.0 → gea_program-0.76.0}/gea/service.py +37 -0
  40. gea_program-0.76.0/gea/tutorial.py +237 -0
  41. {gea_program-0.75.0 → gea_program-0.76.0}/gea/web/app.html +27 -3
  42. {gea_program-0.75.0 → gea_program-0.76.0/gea_program.egg-info}/PKG-INFO +24 -4
  43. {gea_program-0.75.0 → gea_program-0.76.0}/gea_program.egg-info/SOURCES.txt +29 -0
  44. {gea_program-0.75.0 → gea_program-0.76.0}/pyproject.toml +2 -2
  45. {gea_program-0.75.0 → gea_program-0.76.0}/LICENSE +0 -0
  46. {gea_program-0.75.0 → gea_program-0.76.0}/gea/BENCH_TEST_PROTOCOL.md +0 -0
  47. {gea_program-0.75.0 → gea_program-0.76.0}/gea/accuracy_statement.py +0 -0
  48. {gea_program-0.75.0 → gea_program-0.76.0}/gea/alarm_engine.py +0 -0
  49. {gea_program-0.75.0 → gea_program-0.76.0}/gea/alerts.py +0 -0
  50. {gea_program-0.75.0 → gea_program-0.76.0}/gea/backup.py +0 -0
  51. {gea_program-0.75.0 → gea_program-0.76.0}/gea/bench.py +0 -0
  52. {gea_program-0.75.0 → gea_program-0.76.0}/gea/bit_seismic.py +0 -0
  53. {gea_program-0.75.0 → gea_program-0.76.0}/gea/blind_harness.py +0 -0
  54. {gea_program-0.75.0 → gea_program-0.76.0}/gea/casing_design.py +0 -0
  55. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/acex_lomonosov_age_depth_model.provenance.json +0 -0
  56. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/acex_lomonosov_age_depth_model.txt +0 -0
  57. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/agassiz77_canada_temperature.csv +0 -0
  58. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/agassiz77_canada_temperature.provenance.json +0 -0
  59. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/barbados_110_consolidation.provenance.json +0 -0
  60. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/barbados_110_consolidation.txt +0 -0
  61. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/bengal_u1452_grain_size.provenance.json +0 -0
  62. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/bengal_u1452_grain_size.txt +0 -0
  63. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/blake_164_methane_isotopes.provenance.json +0 -0
  64. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/blake_164_methane_isotopes.txt +0 -0
  65. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.provenance.json +0 -0
  66. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.txt +0 -0
  67. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/collingwood_1_28_ks_complete.las +0 -0
  68. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/collingwood_1_28_ks_complete.provenance.json +0 -0
  69. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/costa_rica_odp_friction_envelope.provenance.json +0 -0
  70. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/costa_rica_odp_friction_envelope.txt +0 -0
  71. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.provenance.json +0 -0
  72. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.txt +0 -0
  73. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/dsdp_504b_physical_properties.provenance.json +0 -0
  74. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/dsdp_504b_physical_properties.txt +0 -0
  75. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/dsdp_504b_sound_velocity.provenance.json +0 -0
  76. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/dsdp_504b_sound_velocity.txt +0 -0
  77. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/elgygytgyn_5011_turbidites.provenance.json +0 -0
  78. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/elgygytgyn_5011_turbidites.txt +0 -0
  79. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/epica_domec_co2_800kyr.provenance.json +0 -0
  80. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/epica_domec_co2_800kyr.txt +0 -0
  81. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/fram_909_organic_petrography.provenance.json +0 -0
  82. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/fram_909_organic_petrography.txt +0 -0
  83. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/gbr_325_coral_uth_ages.provenance.json +0 -0
  84. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/gbr_325_coral_uth_ages.txt +0 -0
  85. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/gisp2_greenland_temperature.csv +0 -0
  86. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/gisp2_greenland_temperature.provenance.json +0 -0
  87. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/gom_308_t2p_insitu.provenance.json +0 -0
  88. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/gom_308_t2p_insitu.txt +0 -0
  89. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/guaymas_385_dom_d13c.provenance.json +0 -0
  90. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/guaymas_385_dom_d13c.txt +0 -0
  91. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/hikurangi_u1520_friction_insitu.provenance.json +0 -0
  92. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/hikurangi_u1520_friction_insitu.txt +0 -0
  93. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.provenance.json +0 -0
  94. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.txt +0 -0
  95. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/iodp_u1324_pore_pressure.provenance.json +0 -0
  96. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/iodp_u1324_pore_pressure.txt +0 -0
  97. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/jfast_c0019_slow_slip_events.provenance.json +0 -0
  98. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/jfast_c0019_slow_slip_events.txt +0 -0
  99. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/kennetcook_2_p129_excerpt.las +0 -0
  100. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/kennetcook_2_p129_excerpt.provenance.json +0 -0
  101. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/ktb_hb_bhgm_density.dat +0 -0
  102. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/ktb_hb_bhgm_density.provenance.json +0 -0
  103. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/ktb_hb_complog_6020_excerpt.provenance.json +0 -0
  104. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/ktb_hb_complog_6020_excerpt.txt +0 -0
  105. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/ktb_hb_hlog246_temperature.dat +0 -0
  106. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/ktb_hb_hlog246_temperature.provenance.json +0 -0
  107. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/ktb_hb_rockmech_compress.dat +0 -0
  108. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/ktb_hb_rockmech_compress.provenance.json +0 -0
  109. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.dat +0 -0
  110. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.provenance.json +0 -0
  111. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/ktb_vb_rockmech_compress.dat +0 -0
  112. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/ktb_vb_rockmech_compress.provenance.json +0 -0
  113. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/ktb_vb_vlog251_temperature.dat +0 -0
  114. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/ktb_vb_vlog251_temperature.provenance.json +0 -0
  115. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/l06_06_nl_survey.csv +0 -0
  116. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/l06_06_nl_survey.provenance.json +0 -0
  117. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/l07_01_nl_excerpt.las +0 -0
  118. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/l07_01_nl_excerpt.provenance.json +0 -0
  119. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/mariana_1200_serpentinite_geochem.provenance.json +0 -0
  120. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/mariana_1200_serpentinite_geochem.txt +0 -0
  121. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/med_160_sapropels.provenance.json +0 -0
  122. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/med_160_sapropels.txt +0 -0
  123. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/nankai_megasplay_shear_strength.provenance.json +0 -0
  124. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/nankai_megasplay_shear_strength.txt +0 -0
  125. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/odp_1027b_thermal_conductivity.provenance.json +0 -0
  126. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/odp_1027b_thermal_conductivity.txt +0 -0
  127. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/odp_1027c_cork_temperature.provenance.json +0 -0
  128. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/odp_1027c_cork_temperature.txt +0 -0
  129. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/odp_1165b_thermal_conductivity.provenance.json +0 -0
  130. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/odp_1165b_thermal_conductivity.txt +0 -0
  131. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.provenance.json +0 -0
  132. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.txt +0 -0
  133. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/odp_504b_dike_elastic_moduli.provenance.json +0 -0
  134. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/odp_504b_dike_elastic_moduli.txt +0 -0
  135. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/odp_504b_leg137_borehole_fluids.provenance.json +0 -0
  136. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/odp_504b_leg137_borehole_fluids.txt +0 -0
  137. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.provenance.json +0 -0
  138. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.txt +0 -0
  139. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/peru_201_sulfate_reduction.provenance.json +0 -0
  140. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/peru_201_sulfate_reduction.txt +0 -0
  141. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/scorpio_e1_sa_excerpt.las +0 -0
  142. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/scorpio_e1_sa_excerpt.provenance.json +0 -0
  143. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/sumatra_362_cohesion.provenance.json +0 -0
  144. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/sumatra_362_cohesion.txt +0 -0
  145. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/university_6_17_no1_tx_excerpt.las +0 -0
  146. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/university_6_17_no1_tx_excerpt.provenance.json +0 -0
  147. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/ursa_308_xrd_mineralogy.provenance.json +0 -0
  148. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/ursa_308_xrd_mineralogy.txt +0 -0
  149. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/volve_15_9_19_sr_excerpt.las +0 -0
  150. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/volve_15_9_19_sr_excerpt.provenance.json +0 -0
  151. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/volve_15_9_19a_core_excerpt.csv +0 -0
  152. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/volve_15_9_19a_core_excerpt.provenance.json +0 -0
  153. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/volve_f12_f14_production_excerpt.csv +0 -0
  154. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/volve_f12_f14_production_excerpt.provenance.json +0 -0
  155. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/walvis_208_petm_carbonate.provenance.json +0 -0
  156. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/walvis_208_petm_carbonate.txt +0 -0
  157. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/woodlark_1109_rock_eval.provenance.json +0 -0
  158. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog/woodlark_1109_rock_eval.txt +0 -0
  159. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog_map.py +0 -0
  160. {gea_program-0.75.0 → gea_program-0.76.0}/gea/catalog_register.py +0 -0
  161. {gea_program-0.75.0 → gea_program-0.76.0}/gea/certificates.py +0 -0
  162. {gea_program-0.75.0 → gea_program-0.76.0}/gea/cli.py +0 -0
  163. {gea_program-0.75.0 → gea_program-0.76.0}/gea/client_reports.py +0 -0
  164. {gea_program-0.75.0 → gea_program-0.76.0}/gea/collision.py +0 -0
  165. {gea_program-0.75.0 → gea_program-0.76.0}/gea/config_versioning.py +0 -0
  166. {gea_program-0.75.0 → gea_program-0.76.0}/gea/conformance.py +0 -0
  167. {gea_program-0.75.0 → gea_program-0.76.0}/gea/control_room.py +0 -0
  168. {gea_program-0.75.0 → gea_program-0.76.0}/gea/correlation.py +0 -0
  169. {gea_program-0.75.0 → gea_program-0.76.0}/gea/dashboard.py +0 -0
  170. {gea_program-0.75.0 → gea_program-0.76.0}/gea/declarations.py +0 -0
  171. {gea_program-0.75.0 → gea_program-0.76.0}/gea/decline.py +0 -0
  172. {gea_program-0.75.0 → gea_program-0.76.0}/gea/deviation.py +0 -0
  173. {gea_program-0.75.0 → gea_program-0.76.0}/gea/dlis.py +0 -0
  174. {gea_program-0.75.0 → gea_program-0.76.0}/gea/dnp3.py +0 -0
  175. {gea_program-0.75.0 → gea_program-0.76.0}/gea/doctor.py +0 -0
  176. {gea_program-0.75.0 → gea_program-0.76.0}/gea/dossier.py +0 -0
  177. {gea_program-0.75.0 → gea_program-0.76.0}/gea/dossier_verify.py +0 -0
  178. {gea_program-0.75.0 → gea_program-0.76.0}/gea/downhole_engine.py +0 -0
  179. {gea_program-0.75.0 → gea_program-0.76.0}/gea/drift_monitor.py +0 -0
  180. {gea_program-0.75.0 → gea_program-0.76.0}/gea/drill_string.py +0 -0
  181. {gea_program-0.75.0 → gea_program-0.76.0}/gea/earth_model.py +0 -0
  182. {gea_program-0.75.0 → gea_program-0.76.0}/gea/economics.py +0 -0
  183. {gea_program-0.75.0 → gea_program-0.76.0}/gea/ed25519.py +0 -0
  184. {gea_program-0.75.0 → gea_program-0.76.0}/gea/edr.py +0 -0
  185. {gea_program-0.75.0 → gea_program-0.76.0}/gea/elevation.py +0 -0
  186. {gea_program-0.75.0 → gea_program-0.76.0}/gea/etp.py +0 -0
  187. {gea_program-0.75.0 → gea_program-0.76.0}/gea/etp12_schemas.json +0 -0
  188. {gea_program-0.75.0 → gea_program-0.76.0}/gea/example_register_map.json +0 -0
  189. {gea_program-0.75.0 → gea_program-0.76.0}/gea/fat_sat.py +0 -0
  190. {gea_program-0.75.0 → gea_program-0.76.0}/gea/field_pull.py +0 -0
  191. {gea_program-0.75.0 → gea_program-0.76.0}/gea/files.py +0 -0
  192. {gea_program-0.75.0 → gea_program-0.76.0}/gea/fixtures/README.md +0 -0
  193. {gea_program-0.75.0 → gea_program-0.76.0}/gea/fixtures/comcat_delaware_basin_2026-09.txt +0 -0
  194. {gea_program-0.75.0 → gea_program-0.76.0}/gea/fixtures/comcat_mahoning_1990-2026.txt +0 -0
  195. {gea_program-0.75.0 → gea_program-0.76.0}/gea/fixtures/comcat_youngstown_2011-2012.txt +0 -0
  196. {gea_program-0.75.0 → gea_program-0.76.0}/gea/fixtures/ne_110m_coastline.json +0 -0
  197. {gea_program-0.75.0 → gea_program-0.76.0}/gea/follower.py +0 -0
  198. {gea_program-0.75.0 → gea_program-0.76.0}/gea/forward_model.py +0 -0
  199. {gea_program-0.75.0 → gea_program-0.76.0}/gea/frac_hits.py +0 -0
  200. {gea_program-0.75.0 → gea_program-0.76.0}/gea/friction_priors.py +0 -0
  201. {gea_program-0.75.0 → gea_program-0.76.0}/gea/gamma.py +0 -0
  202. {gea_program-0.75.0 → gea_program-0.76.0}/gea/gauge_aging.py +0 -0
  203. {gea_program-0.75.0 → gea_program-0.76.0}/gea/gauge_specs.py +0 -0
  204. {gea_program-0.75.0 → gea_program-0.76.0}/gea/geodesy.py +0 -0
  205. {gea_program-0.75.0 → gea_program-0.76.0}/gea/geomag.py +0 -0
  206. {gea_program-0.75.0 → gea_program-0.76.0}/gea/gravity_reference.py +0 -0
  207. {gea_program-0.75.0 → gea_program-0.76.0}/gea/hartip.py +0 -0
  208. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/TESTER_GUIDE.md +0 -0
  209. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/alarms.md +0 -0
  210. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/alerts.md +0 -0
  211. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/audit-update.md +0 -0
  212. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/backup.md +0 -0
  213. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/bit-image.md +0 -0
  214. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/casing.md +0 -0
  215. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/catalog.md +0 -0
  216. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/charts.md +0 -0
  217. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/collision.md +0 -0
  218. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/company-sign-in.md +0 -0
  219. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/conformance.md +0 -0
  220. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/control-room.md +0 -0
  221. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/data-in.md +0 -0
  222. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/declare.md +0 -0
  223. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/decline.md +0 -0
  224. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/dlis.md +0 -0
  225. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/doctor.md +0 -0
  226. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/dossier.md +0 -0
  227. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/drift.md +0 -0
  228. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/drillstring.md +0 -0
  229. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/economics.md +0 -0
  230. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/edr.md +0 -0
  231. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/etp.md +0 -0
  232. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/field-ports.md +0 -0
  233. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/files.md +0 -0
  234. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/frac-hits.md +0 -0
  235. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/historian.md +0 -0
  236. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/https.md +0 -0
  237. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/hydraulics.md +0 -0
  238. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/instruments.md +0 -0
  239. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/interval.md +0 -0
  240. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/invoice-check.md +0 -0
  241. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/map.md +0 -0
  242. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/month-end.md +0 -0
  243. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/notifications.md +0 -0
  244. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/opseis.md +0 -0
  245. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/osdu.md +0 -0
  246. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/pad-summary.md +0 -0
  247. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/patches.md +0 -0
  248. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/penetrator.md +0 -0
  249. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/plan.md +0 -0
  250. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/pore-pressure.md +0 -0
  251. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/ppdm.md +0 -0
  252. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/quakeml.md +0 -0
  253. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/quality.md +0 -0
  254. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/records.md +0 -0
  255. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/report-history.md +0 -0
  256. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/rig-time.md +0 -0
  257. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/rocks.md +0 -0
  258. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/seedlink.md +0 -0
  259. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/seismic.md +0 -0
  260. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/setup.md +0 -0
  261. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/simulation.md +0 -0
  262. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/site.md +0 -0
  263. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/sites.md +0 -0
  264. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/slip.md +0 -0
  265. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/soak.md +0 -0
  266. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/sra.md +0 -0
  267. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/start.md +0 -0
  268. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/structure.md +0 -0
  269. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/tools.md +0 -0
  270. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/torque-drag.md +0 -0
  271. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/transients.md +0 -0
  272. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/upkeep.md +0 -0
  273. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/vibration.md +0 -0
  274. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/vpn.md +0 -0
  275. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/well-report.md +0 -0
  276. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/well-tests.md +0 -0
  277. {gea_program-0.75.0 → gea_program-0.76.0}/gea/help/well3d.md +0 -0
  278. {gea_program-0.75.0 → gea_program-0.76.0}/gea/housekeeping.py +0 -0
  279. {gea_program-0.75.0 → gea_program-0.76.0}/gea/hydraulics.py +0 -0
  280. {gea_program-0.75.0 → gea_program-0.76.0}/gea/icon.py +0 -0
  281. {gea_program-0.75.0 → gea_program-0.76.0}/gea/interval.py +0 -0
  282. {gea_program-0.75.0 → gea_program-0.76.0}/gea/inverse_engine.py +0 -0
  283. {gea_program-0.75.0 → gea_program-0.76.0}/gea/invoice_check.py +0 -0
  284. {gea_program-0.75.0 → gea_program-0.76.0}/gea/jobs.py +0 -0
  285. {gea_program-0.75.0 → gea_program-0.76.0}/gea/launcher.py +0 -0
  286. {gea_program-0.75.0 → gea_program-0.76.0}/gea/live_ports.py +0 -0
  287. {gea_program-0.75.0 → gea_program-0.76.0}/gea/loadtest.py +0 -0
  288. {gea_program-0.75.0 → gea_program-0.76.0}/gea/matplotlib_demo.py +0 -0
  289. {gea_program-0.75.0 → gea_program-0.76.0}/gea/modbus.py +0 -0
  290. {gea_program-0.75.0 → gea_program-0.76.0}/gea/modbus_rtu.py +0 -0
  291. {gea_program-0.75.0 → gea_program-0.76.0}/gea/model_card.py +0 -0
  292. {gea_program-0.75.0 → gea_program-0.76.0}/gea/month_end.py +0 -0
  293. {gea_program-0.75.0 → gea_program-0.76.0}/gea/mqtt_port.py +0 -0
  294. {gea_program-0.75.0 → gea_program-0.76.0}/gea/notify.py +0 -0
  295. {gea_program-0.75.0 → gea_program-0.76.0}/gea/oidc.py +0 -0
  296. {gea_program-0.75.0 → gea_program-0.76.0}/gea/oidc_mock.py +0 -0
  297. {gea_program-0.75.0 → gea_program-0.76.0}/gea/op_seismicity.py +0 -0
  298. {gea_program-0.75.0 → gea_program-0.76.0}/gea/opcua_port.py +0 -0
  299. {gea_program-0.75.0 → gea_program-0.76.0}/gea/operator_app.py +0 -0
  300. {gea_program-0.75.0 → gea_program-0.76.0}/gea/osdu.py +0 -0
  301. {gea_program-0.75.0 → gea_program-0.76.0}/gea/pad_summary.py +0 -0
  302. {gea_program-0.75.0 → gea_program-0.76.0}/gea/patches.py +0 -0
  303. {gea_program-0.75.0 → gea_program-0.76.0}/gea/pdf_report.py +0 -0
  304. {gea_program-0.75.0 → gea_program-0.76.0}/gea/penetrator.py +0 -0
  305. {gea_program-0.75.0 → gea_program-0.76.0}/gea/permits.py +0 -0
  306. {gea_program-0.75.0 → gea_program-0.76.0}/gea/piwebapi.py +0 -0
  307. {gea_program-0.75.0 → gea_program-0.76.0}/gea/pore_pressure.py +0 -0
  308. {gea_program-0.75.0 → gea_program-0.76.0}/gea/ports.py +0 -0
  309. {gea_program-0.75.0 → gea_program-0.76.0}/gea/ppdm.py +0 -0
  310. {gea_program-0.75.0 → gea_program-0.76.0}/gea/profile_catalog.py +0 -0
  311. {gea_program-0.75.0 → gea_program-0.76.0}/gea/project.py +0 -0
  312. {gea_program-0.75.0 → gea_program-0.76.0}/gea/qt6_downhole_app.py +0 -0
  313. {gea_program-0.75.0 → gea_program-0.76.0}/gea/quakeml.py +0 -0
  314. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reader.py +0 -0
  315. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reader_app.py +0 -0
  316. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reconciler.py +0 -0
  317. {gea_program-0.75.0 → gea_program-0.76.0}/gea/recorder_link.py +0 -0
  318. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/IU_ANMO_10_BHZ_response.provenance.json +0 -0
  319. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/IU_ANMO_10_BHZ_response.xml +0 -0
  320. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/WMM2025.COF +0 -0
  321. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/eia_henry_hub_daily.csv.gz +0 -0
  322. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/eia_prices.provenance.json +0 -0
  323. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/eia_wti_daily.csv.gz +0 -0
  324. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/iscwsa_rev4_example.json +0 -0
  325. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/iscwsa_rev5_example.json +0 -0
  326. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/l0701_sonic_gr.las.gz +0 -0
  327. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/l0701_sonic_gr.provenance.json +0 -0
  328. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/libmseed_steim.provenance.json +0 -0
  329. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/libmseed_steim1_4096.mseed +0 -0
  330. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/libmseed_steim2_4096.mseed +0 -0
  331. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/libmseed_steim2_512.mseed +0 -0
  332. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/mahoning_example.json +0 -0
  333. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/mud_motor_specs.json +0 -0
  334. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/owsg_tool_models.json +0 -0
  335. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/penetrator_ratings.json +0 -0
  336. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/seismicity_protocols.json +0 -0
  337. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/tool_sources.json +0 -0
  338. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/us_outline.json +0 -0
  339. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/us_outline.provenance.json +0 -0
  340. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/volve_3d.provenance.json +0 -0
  341. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/volve_f4_interpretation.las.gz +0 -0
  342. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/volve_f4_logs.provenance.json +0 -0
  343. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/volve_f4_lwd.las.gz +0 -0
  344. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/volve_surfaces.json.gz +0 -0
  345. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/volve_traj_F-10.xml.gz +0 -0
  346. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/volve_traj_F-4.xml.gz +0 -0
  347. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/volve_traj_F-5_12.25in.xml.gz +0 -0
  348. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/volve_traj_F-5_17.5in.xml.gz +0 -0
  349. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/volve_traj_F-5_36in.xml.gz +0 -0
  350. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/volve_traj_F-5_8.5in.xml.gz +0 -0
  351. {gea_program-0.75.0 → gea_program-0.76.0}/gea/reference/volve_well_picks.csv.gz +0 -0
  352. {gea_program-0.75.0 → gea_program-0.76.0}/gea/report_history.py +0 -0
  353. {gea_program-0.75.0 → gea_program-0.76.0}/gea/rig_state.py +0 -0
  354. {gea_program-0.75.0 → gea_program-0.76.0}/gea/rock_inventory.py +0 -0
  355. {gea_program-0.75.0 → gea_program-0.76.0}/gea/sample_record.py +0 -0
  356. {gea_program-0.75.0 → gea_program-0.76.0}/gea/sample_well_profile.csv +0 -0
  357. {gea_program-0.75.0 → gea_program-0.76.0}/gea/sbom.py +0 -0
  358. {gea_program-0.75.0 → gea_program-0.76.0}/gea/seedlink.py +0 -0
  359. {gea_program-0.75.0 → gea_program-0.76.0}/gea/segy.py +0 -0
  360. {gea_program-0.75.0 → gea_program-0.76.0}/gea/seismic.py +0 -0
  361. {gea_program-0.75.0 → gea_program-0.76.0}/gea/seismic_array.py +0 -0
  362. {gea_program-0.75.0 → gea_program-0.76.0}/gea/seismic_assoc.py +0 -0
  363. {gea_program-0.75.0 → gea_program-0.76.0}/gea/seismic_detect.py +0 -0
  364. {gea_program-0.75.0 → gea_program-0.76.0}/gea/seismic_film.py +0 -0
  365. {gea_program-0.75.0 → gea_program-0.76.0}/gea/seismic_harmonic.py +0 -0
  366. {gea_program-0.75.0 → gea_program-0.76.0}/gea/seismic_qc.py +0 -0
  367. {gea_program-0.75.0 → gea_program-0.76.0}/gea/seismic_response.py +0 -0
  368. {gea_program-0.75.0 → gea_program-0.76.0}/gea/seismic_signature.py +0 -0
  369. {gea_program-0.75.0 → gea_program-0.76.0}/gea/seismic_track.py +0 -0
  370. {gea_program-0.75.0 → gea_program-0.76.0}/gea/seismic_uncertainty.py +0 -0
  371. {gea_program-0.75.0 → gea_program-0.76.0}/gea/seismic_unlisted.py +0 -0
  372. {gea_program-0.75.0 → gea_program-0.76.0}/gea/seismic_watch.py +0 -0
  373. {gea_program-0.75.0 → gea_program-0.76.0}/gea/sensor_swap.py +0 -0
  374. {gea_program-0.75.0 → gea_program-0.76.0}/gea/series_cache.py +0 -0
  375. {gea_program-0.75.0 → gea_program-0.76.0}/gea/service_life.py +0 -0
  376. {gea_program-0.75.0 → gea_program-0.76.0}/gea/setup_checklist.py +0 -0
  377. {gea_program-0.75.0 → gea_program-0.76.0}/gea/shapefile.py +0 -0
  378. {gea_program-0.75.0 → gea_program-0.76.0}/gea/shell.py +0 -0
  379. {gea_program-0.75.0 → gea_program-0.76.0}/gea/shut_in.py +0 -0
  380. {gea_program-0.75.0 → gea_program-0.76.0}/gea/simulation.py +0 -0
  381. {gea_program-0.75.0 → gea_program-0.76.0}/gea/site_map.py +0 -0
  382. {gea_program-0.75.0 → gea_program-0.76.0}/gea/sla_report.py +0 -0
  383. {gea_program-0.75.0 → gea_program-0.76.0}/gea/slip.py +0 -0
  384. {gea_program-0.75.0 → gea_program-0.76.0}/gea/soak.py +0 -0
  385. {gea_program-0.75.0 → gea_program-0.76.0}/gea/sra.py +0 -0
  386. {gea_program-0.75.0 → gea_program-0.76.0}/gea/store_forward.py +0 -0
  387. {gea_program-0.75.0 → gea_program-0.76.0}/gea/strata_join.py +0 -0
  388. {gea_program-0.75.0 → gea_program-0.76.0}/gea/structure.py +0 -0
  389. {gea_program-0.75.0 → gea_program-0.76.0}/gea/supervisor.py +0 -0
  390. {gea_program-0.75.0 → gea_program-0.76.0}/gea/survey_cmd.py +0 -0
  391. {gea_program-0.75.0 → gea_program-0.76.0}/gea/survey_view.py +0 -0
  392. {gea_program-0.75.0 → gea_program-0.76.0}/gea/telemetry.py +0 -0
  393. {gea_program-0.75.0 → gea_program-0.76.0}/gea/timestamp.py +0 -0
  394. {gea_program-0.75.0 → gea_program-0.76.0}/gea/tls.py +0 -0
  395. {gea_program-0.75.0 → gea_program-0.76.0}/gea/tool_catalog.py +0 -0
  396. {gea_program-0.75.0 → gea_program-0.76.0}/gea/tool_library.py +0 -0
  397. {gea_program-0.75.0 → gea_program-0.76.0}/gea/tool_taxonomy.py +0 -0
  398. {gea_program-0.75.0 → gea_program-0.76.0}/gea/torque_drag.py +0 -0
  399. {gea_program-0.75.0 → gea_program-0.76.0}/gea/transient.py +0 -0
  400. {gea_program-0.75.0 → gea_program-0.76.0}/gea/tray.py +0 -0
  401. {gea_program-0.75.0 → gea_program-0.76.0}/gea/updates.py +0 -0
  402. {gea_program-0.75.0 → gea_program-0.76.0}/gea/vibration.py +0 -0
  403. {gea_program-0.75.0 → gea_program-0.76.0}/gea/vpn.py +0 -0
  404. {gea_program-0.75.0 → gea_program-0.76.0}/gea/web/reader.html +0 -0
  405. {gea_program-0.75.0 → gea_program-0.76.0}/gea/well3d.py +0 -0
  406. {gea_program-0.75.0 → gea_program-0.76.0}/gea/well_assembler.py +0 -0
  407. {gea_program-0.75.0 → gea_program-0.76.0}/gea/well_records.py +0 -0
  408. {gea_program-0.75.0 → gea_program-0.76.0}/gea/well_report.py +0 -0
  409. {gea_program-0.75.0 → gea_program-0.76.0}/gea/well_test_validation.py +0 -0
  410. {gea_program-0.75.0 → gea_program-0.76.0}/gea/wellplan.py +0 -0
  411. {gea_program-0.75.0 → gea_program-0.76.0}/gea/wellpos.py +0 -0
  412. {gea_program-0.75.0 → gea_program-0.76.0}/gea/winident.py +0 -0
  413. {gea_program-0.75.0 → gea_program-0.76.0}/gea/wits0.py +0 -0
  414. {gea_program-0.75.0 → gea_program-0.76.0}/gea/witsml.py +0 -0
  415. {gea_program-0.75.0 → gea_program-0.76.0}/gea/workspace.py +0 -0
  416. {gea_program-0.75.0 → gea_program-0.76.0}/gea/workspaces.py +0 -0
  417. {gea_program-0.75.0 → gea_program-0.76.0}/gea/x25519.py +0 -0
  418. {gea_program-0.75.0 → gea_program-0.76.0}/gea/xlsx_read.py +0 -0
  419. {gea_program-0.75.0 → gea_program-0.76.0}/gea_program.egg-info/dependency_links.txt +0 -0
  420. {gea_program-0.75.0 → gea_program-0.76.0}/gea_program.egg-info/entry_points.txt +0 -0
  421. {gea_program-0.75.0 → gea_program-0.76.0}/gea_program.egg-info/requires.txt +0 -0
  422. {gea_program-0.75.0 → gea_program-0.76.0}/gea_program.egg-info/top_level.txt +0 -0
  423. {gea_program-0.75.0 → gea_program-0.76.0}/setup.cfg +0 -0
  424. {gea_program-0.75.0 → gea_program-0.76.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.75.0
3
+ Version: 0.76.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,6 +463,26 @@ 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
+ ### The tutorial
467
+
468
+ Every step of GEA and the programs around it, as 27 lessons on the
469
+ **Tutorial** tab (since 0.76.0; `gea help tutorial`): the office's lessons
470
+ first - install, sign in, set up the site, bring wells and data in, the
471
+ well page, the declarations sheet, the patch panel, alarms and
472
+ notifications, the control room, the daily summary and the month-end
473
+ packet, the map and the 3D view, the drilling and production pages,
474
+ seismic, the recorder from the office, reports, the signed dossier and the
475
+ Reader, users and HTTPS, backups and the gate, new versions from inside
476
+ the program, GEA-VPN - and the pad attendant's after: the box and its
477
+ 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
479
+ (a button opens it), how long it takes, the numbered steps with the
480
+ buttons as the page names them, and how you know it worked; each account
481
+ ticks lessons off. **Print the handout** gives the whole course as one
482
+ page for the people who do not sit at the screen. From a terminal:
483
+ `gea tutorial`, `gea tutorial --lesson 3`, `gea tutorial --handout
484
+ --workspace C:\site`.
485
+
466
486
  ### GEA-VPN: the programs on separate computers, one private network
467
487
 
468
488
  The control panel, each pad's recorder, the operator's window and the
@@ -780,7 +800,7 @@ unsigned, the key hand-overs - and shows the reports as they were signed. A
780
800
  reader made from the workspace knows the site's key fingerprints, so it
781
801
  says whether a dossier is the site's; it allows no network request, and it
782
802
  leaves the trusted time-stamp to `verify_dossier.py`. For a client who wants
783
- it installed, every release also carries `GEA-Reader-Setup-0.75.0.exe`: GEA
803
+ it installed, every release also carries `GEA-Reader-Setup-0.76.0.exe`: GEA
784
804
  Reader as a Windows program of its own - its own icon and taskbar button,
785
805
  Check with GEA Reader on a dossier's right-click menu, fingerprints the client
786
806
  saves kept on that computer, nothing of GEA-Program. `gea help reader`.
@@ -1545,7 +1565,7 @@ attaches the zips to the GitHub release of that tag.
1545
1565
 
1546
1566
  ### The Windows installer
1547
1567
 
1548
- Every release also carries `GEA-Program-Setup-0.75.0.exe` (for 0.75.0): the
1568
+ Every release also carries `GEA-Program-Setup-0.76.0.exe` (for 0.76.0): the
1549
1569
  same Windows kit installed like any Windows program, for the signed-in user
1550
1570
  alone and with no administrator rights (`%LOCALAPPDATA%\Programs\GEA-Program`).
1551
1571
  It asks for the site workspace (an existing one such as `C:\site` is used as
@@ -1564,7 +1584,7 @@ it, removes the program and leaves the workspace. Silent, for a site's
1564
1584
  software deployment:
1565
1585
 
1566
1586
  ```
1567
- GEA-Program-Setup-0.75.0.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /WORKSPACE="C:\site" /SITENAME="Pad 3" /TASKS="desktopicon"
1587
+ GEA-Program-Setup-0.76.0.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /WORKSPACE="C:\site" /SITENAME="Pad 3" /TASKS="desktopicon"
1568
1588
  ```
1569
1589
 
1570
1590
  The setup is built by Inno Setup 6 from `tools/installer.iss` in the same
@@ -424,6 +424,26 @@ 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
+ ### The tutorial
428
+
429
+ Every step of GEA and the programs around it, as 27 lessons on the
430
+ **Tutorial** tab (since 0.76.0; `gea help tutorial`): the office's lessons
431
+ first - install, sign in, set up the site, bring wells and data in, the
432
+ well page, the declarations sheet, the patch panel, alarms and
433
+ notifications, the control room, the daily summary and the month-end
434
+ packet, the map and the 3D view, the drilling and production pages,
435
+ seismic, the recorder from the office, reports, the signed dossier and the
436
+ Reader, users and HTTPS, backups and the gate, new versions from inside
437
+ the program, GEA-VPN - and the pad attendant's after: the box and its
438
+ 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
440
+ (a button opens it), how long it takes, the numbered steps with the
441
+ buttons as the page names them, and how you know it worked; each account
442
+ ticks lessons off. **Print the handout** gives the whole course as one
443
+ page for the people who do not sit at the screen. From a terminal:
444
+ `gea tutorial`, `gea tutorial --lesson 3`, `gea tutorial --handout
445
+ --workspace C:\site`.
446
+
427
447
  ### GEA-VPN: the programs on separate computers, one private network
428
448
 
429
449
  The control panel, each pad's recorder, the operator's window and the
@@ -741,7 +761,7 @@ unsigned, the key hand-overs - and shows the reports as they were signed. A
741
761
  reader made from the workspace knows the site's key fingerprints, so it
742
762
  says whether a dossier is the site's; it allows no network request, and it
743
763
  leaves the trusted time-stamp to `verify_dossier.py`. For a client who wants
744
- it installed, every release also carries `GEA-Reader-Setup-0.75.0.exe`: GEA
764
+ it installed, every release also carries `GEA-Reader-Setup-0.76.0.exe`: GEA
745
765
  Reader as a Windows program of its own - its own icon and taskbar button,
746
766
  Check with GEA Reader on a dossier's right-click menu, fingerprints the client
747
767
  saves kept on that computer, nothing of GEA-Program. `gea help reader`.
@@ -1506,7 +1526,7 @@ attaches the zips to the GitHub release of that tag.
1506
1526
 
1507
1527
  ### The Windows installer
1508
1528
 
1509
- Every release also carries `GEA-Program-Setup-0.75.0.exe` (for 0.75.0): the
1529
+ Every release also carries `GEA-Program-Setup-0.76.0.exe` (for 0.76.0): the
1510
1530
  same Windows kit installed like any Windows program, for the signed-in user
1511
1531
  alone and with no administrator rights (`%LOCALAPPDATA%\Programs\GEA-Program`).
1512
1532
  It asks for the site workspace (an existing one such as `C:\site` is used as
@@ -1525,7 +1545,7 @@ it, removes the program and leaves the workspace. Silent, for a site's
1525
1545
  software deployment:
1526
1546
 
1527
1547
  ```
1528
- GEA-Program-Setup-0.75.0.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /WORKSPACE="C:\site" /SITENAME="Pad 3" /TASKS="desktopicon"
1548
+ GEA-Program-Setup-0.76.0.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /WORKSPACE="C:\site" /SITENAME="Pad 3" /TASKS="desktopicon"
1529
1549
  ```
1530
1550
 
1531
1551
  The setup is built by Inno Setup 6 from `tools/installer.iss` in the same
@@ -123,7 +123,7 @@ from .profile_catalog import (
123
123
  read_pangaea_txt,
124
124
  )
125
125
 
126
- __version__ = "0.75.0"
126
+ __version__ = "0.76.0"
127
127
  __all__ = [
128
128
  "aging_rate", "rate_psi_yr", "accuracy_psi",
129
129
  "Sensor", "SimulatorConfig", "DownholeEngine",
@@ -1023,6 +1023,15 @@ def main(argv=None) -> int:
1023
1023
  p_up.add_argument("--install", type=str, default=None, help="run the fetched GEA-Program-Setup of this version (Windows): the control panel stops and comes back")
1024
1024
  p_up.add_argument("--actor", type=str, default="cli")
1025
1025
 
1026
+ p_tu = sub.add_parser("tutorial", help="the tutorial: every step of GEA and the programs around it as lessons - list them, print one, write the handout (the Tutorial tab does the same by clicking)")
1027
+ p_tu.add_argument("--lesson", type=str, default=None, help="print one lesson by its number (3) or its name (install)")
1028
+ p_tu.add_argument("--handout", action="store_true", help="write the whole course as one printable HTML page (and Markdown)")
1029
+ p_tu.add_argument("--workspace", type=str, default=None, help="with --handout: the workspace whose exports\\tutorial folder gets it (C:\\site); with a workspace, --user shows that person's progress")
1030
+ p_tu.add_argument("--out", type=str, default=None, help="with --handout and no workspace: the HTML file to write (C:\\site\\GEA-Tutorial.html)")
1031
+ p_tu.add_argument("--user", type=str, default="", help="whose progress to show")
1032
+ p_tu.add_argument("--actor", type=str, default="cli")
1033
+ p_tu.add_argument("--json", action="store_true")
1034
+
1026
1035
  p_vp = sub.add_parser("vpn", help="GEA-VPN: the private WireGuard network the programs talk over - make it, add and remove members, write the hub installer and every member's configuration (the Administration card does the same by clicking)")
1027
1036
  p_vp.add_argument("--workspace", type=str, default=None, help="the workspace (C:\\site); keys in keys\\vpn\\network.json, files under exports\\vpn")
1028
1037
  p_vp.add_argument("--create", type=str, default=None, metavar="HOST", help="make the network with the hub at this public name or address (vpn.pad3site.com or 203.0.113.10); the office member is made with it")
@@ -2371,6 +2380,34 @@ def main(argv=None) -> int:
2371
2380
  return 0
2372
2381
  from .doctor import update as _update
2373
2382
  return _update(check_only=a.check, extras=a.extras, as_json=a.json)
2383
+ elif a.cmd == "tutorial":
2384
+ import json as _json
2385
+ from . import tutorial as TU
2386
+ ws = None
2387
+ if a.workspace or os.environ.get("GEA_WORKSPACE"):
2388
+ from .workspace import Workspace
2389
+ ws = Workspace(a.workspace or os.environ.get("GEA_WORKSPACE"))
2390
+ if a.handout:
2391
+ if ws is not None:
2392
+ r = TU.write_handout(ws, a.actor, __version__)
2393
+ print(f"written: {r['html']} and {r['md']} ({r['lessons']} lessons); open the HTML and print it for the PDF")
2394
+ return 0
2395
+ out = a.out or f"GEA-Tutorial-{__version__}.html"
2396
+ with open(out, "w", encoding="utf-8") as f:
2397
+ f.write(TU.handout_html(__version__))
2398
+ print(f"written: {out} ({len(TU.lessons())} lessons); open it and print it for the PDF")
2399
+ return 0
2400
+ if a.lesson:
2401
+ les = TU.lesson(a.lesson)
2402
+ if les is None:
2403
+ raise SystemExit(f"tutorial: no lesson {a.lesson}; `gea tutorial` lists them")
2404
+ print(_json.dumps({k: v for k, v in les.items() if k not in ("path", "html")}, indent=1) if a.json else les["markdown"])
2405
+ return 0
2406
+ if a.json:
2407
+ print(_json.dumps(TU.overview(ws, a.user), indent=1))
2408
+ else:
2409
+ print(TU.text(ws, a.user))
2410
+ return 0
2374
2411
  elif a.cmd == "vpn":
2375
2412
  import json as _json
2376
2413
  from . import vpn as VP
@@ -16101,7 +16101,7 @@ def section_dt_vpn(tmp: str) -> None:
16101
16101
  b_pub = "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f"
16102
16102
  shared = "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742"
16103
16103
  pub_a = X.public_key(a_priv); pub_b = X.public_key(b_priv)
16104
- wg = shutil.which("wg")
16104
+ wg = shutil.which("wg") if os.name != "nt" else None
16105
16105
  wg_same = None
16106
16106
  if wg:
16107
16107
  try:
@@ -16179,14 +16179,20 @@ def section_dt_vpn(tmp: str) -> None:
16179
16179
  box_names = sorted(n.split("/", 1)[1] for n in z.namelist()); box_conf_z = z.read(f"gea-vpn-{box['id']}/gea-vpn.conf").decode(); vpn_sh = z.read(f"gea-vpn-{box['id']}/vpn.sh").decode()
16180
16180
  with zipfile.ZipFile(rd_zip) as z:
16181
16181
  rd_names = sorted(n.split("/", 1)[1] for n in z.namelist())
16182
- sh = shutil.which("sh")
16182
+ sh = shutil.which("sh") if os.name != "nt" else None # the scripts run on Linux hosts; Git's sh.exe on a Windows machine is not that
16183
16183
  sh_ok = None
16184
16184
  if sh:
16185
- sh_ok = all(subprocess.run([sh, "-n", str(root / f)], capture_output=True, timeout=10).returncode == 0 for f in ("hub/install-hub.sh", f"{box['id']}/vpn.sh"))
16186
- wgq = shutil.which("wg-quick")
16185
+ try:
16186
+ sh_ok = all(any(subprocess.run([sh, "-n", str(root / f)], capture_output=True, timeout=20).returncode == 0 for _ in range(2)) for f in ("hub/install-hub.sh", f"{box['id']}/vpn.sh"))
16187
+ except (OSError, subprocess.SubprocessError):
16188
+ sh_ok = None
16189
+ wgq = shutil.which("wg-quick") if os.name != "nt" else None
16187
16190
  strip_ok = None
16188
16191
  if wgq:
16189
- strip_ok = all(subprocess.run([wgq, "strip", str(root / f)], capture_output=True, timeout=10).returncode == 0 for f in ("hub/gea-vpn.conf", f"{box['id']}/gea-vpn.conf", "office/gea-vpn.conf"))
16192
+ try:
16193
+ strip_ok = all(any(subprocess.run([wgq, "strip", str(root / f)], capture_output=True, timeout=20).returncode == 0 for _ in range(2)) for f in ("hub/gea-vpn.conf", f"{box['id']}/gea-vpn.conf", "office/gea-vpn.conf"))
16194
+ except (OSError, subprocess.SubprocessError):
16195
+ strip_ok = None
16190
16196
  removed = VP.remove_member(ws, "tester", rd["id"])
16191
16197
  rd_gone_at_once = not rd_zip.exists() and not (root / rd["id"]).exists()
16192
16198
  VP.write_bundles(ws, "tester")
@@ -16278,6 +16284,131 @@ def section_dt_vpn(tmp: str) -> None:
16278
16284
  "and the help page carry it" + (f" [failed: {', '.join(failed4)}]" if failed4 else ""))
16279
16285
 
16280
16286
 
16287
+ def section_du_tutorial(tmp: str) -> None:
16288
+ """Section DU - the tutorial: every lesson held to its contract (the header, who and where, numbered steps, the
16289
+ "you know it worked when" section, help pages that exist, a page that exists in the control panel, no
16290
+ placeholder); every page the lessons name is a page of the control panel and every button a lesson names in
16291
+ bold is on that page or in a help page; progress kept per account; the handout written whole; the routes, the
16292
+ tab, the command and the help page."""
16293
+ import http.cookiejar
16294
+ import urllib.error
16295
+ import urllib.request
16296
+ from . import __version__
16297
+ from . import helplib as H
16298
+ from . import tutorial as TU
16299
+ from .service import Service, Users
16300
+ from .workspace import Workspace
16301
+ pkg = Path(__file__).parent
16302
+ d = Path(tmp, "du"); d.mkdir()
16303
+ app_src = (pkg / "web" / "app.html").read_text(encoding="utf-8")
16304
+ main_src = (pkg / "__main__.py").read_text(encoding="utf-8")
16305
+ help_all = "\n".join((pkg / "help" / f).read_text(encoding="utf-8") for f in os.listdir(pkg / "help") if f.endswith(".md"))
16306
+ # -- DU1 the lessons against the contract ------------------------------------------------------------------------------
16307
+ ls = TU.lessons()
16308
+ nav = re.search(r"const NAV = \[(.*?)\];", app_src)
16309
+ views = set(re.findall(r"'(#/[a-z0-9]*)'", nav.group(1))) if nav else set()
16310
+ bad_contract = {l["id"]: TU.check(l["id"]) for l in ls if TU.check(l["id"])}
16311
+ bad_where = [l["id"] for l in ls if l["where"] not in views]
16312
+ numbers = [l["n"] for l in ls]
16313
+ # every **Button** a lesson names must be on the page or in a help page (the lessons describe what is there)
16314
+ unknown_buttons = []
16315
+ for l in ls:
16316
+ body = TU.lesson(l["id"])["body"]
16317
+ for b in re.findall(r"\*\*([^*]+)\*\*", body):
16318
+ b_ = b.rstrip(".:")
16319
+ if len(b_) > 48 or b_[0].islower() or b_ in ("You know it worked when",):
16320
+ continue
16321
+ key = b_.replace("...", "").strip()
16322
+ if key and key not in app_src and key not in help_all and key not in body.replace("**", "").replace(key, "", 1):
16323
+ unknown_buttons.append(f"{l['n']}: {b_}")
16324
+ parts_cover = all(any(a <= n <= b for name, (a, b) in TU.PARTS) for n in numbers)
16325
+ c1 = {
16326
+ "count": len(ls) >= 27 and numbers == list(range(1, len(ls) + 1)),
16327
+ "contract": not bad_contract,
16328
+ "pages_exist": not bad_where,
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) == 8,
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")),
16333
+ }
16334
+ failed1 = [k for k, v in c1.items() if not v]
16335
+ ok(not failed1,
16336
+ f"DU1 the {len(ls)} lessons are numbered without a gap, each with who it is for, the page it is done on (a page of the control panel), how long, "
16337
+ "a summary, three or more numbered steps, the \"you know it worked when\" section and help pages that exist; every button named in bold is on "
16338
+ "the page or in a help page; both audiences, eight parts; install, the reader, the recorder, the VPN, the dossier, the patches and the backup "
16339
+ "each have a lesson" + (f" [failed: {', '.join(failed1)}" + (f"; {list(bad_contract.items())[:2]}" if bad_contract else "") + (f"; where {bad_where}" if bad_where else "")
16340
+ + (f"; buttons {unknown_buttons[:4]}" if unknown_buttons else "") + "]" if failed1 else ""))
16341
+ # -- DU2 progress, the handout, the routes, the tab, the command, the help ----------------------------------------------
16342
+ ws = Workspace.create(str(d / "ws"), "Pad 3 tutorial", actor="tester")
16343
+ m1 = TU.mark(ws, "op", "install")
16344
+ m2 = TU.mark(ws, "op", "3")
16345
+ m3 = TU.mark(ws, "viewer", "install")
16346
+ ov = TU.overview(ws, "op")
16347
+ TU.mark(ws, "op", "install", done=False)
16348
+ ov2 = TU.overview(ws, "op")
16349
+ try:
16350
+ TU.mark(ws, "op", "nothing-of-the-kind"); mark_bad = False
16351
+ except KeyError:
16352
+ mark_bad = True
16353
+ hand = TU.write_handout(ws, "tester", __version__)
16354
+ hh = Path(hand["html"]).read_text(encoding="utf-8")
16355
+ hm = Path(hand["md"]).read_text(encoding="utf-8")
16356
+ Users(str(Path(ws.path, "users.json"))).add("op", "op-pass-123", "operator")
16357
+ Users(str(Path(ws.path, "users.json"))).add("vw", "vw-pass-123", "viewer")
16358
+ svc = Service(ws.path, port=0, scheduler=False).start()
16359
+ base = svc.url.rstrip("/")
16360
+
16361
+ def opener_():
16362
+ return urllib.request.build_opener(urllib.request.HTTPCookieProcessor(http.cookiejar.CookieJar()))
16363
+
16364
+ def call(op, method, path, body=None, raw_=False):
16365
+ rq = urllib.request.Request(base + path, method=method, data=(json.dumps(body).encode() if body is not None else None))
16366
+ rq.add_header("Content-Type", "application/json"); rq.add_header("X-GEA-Action", "1")
16367
+ try:
16368
+ with op.open(rq, timeout=60) as rr_:
16369
+ data = rr_.read()
16370
+ return rr_.status, (data if raw_ else json.loads(data)), rr_.headers
16371
+ except urllib.error.HTTPError as e:
16372
+ return e.code, (e.read() if raw_ else json.loads(e.read() or b"{}")), e.headers
16373
+ try:
16374
+ anon = opener_()
16375
+ s_anon, _, _ = call(anon, "GET", "/api/tutorial")
16376
+ vw = opener_(); call(vw, "POST", "/api/login", {"name": "vw", "password": "vw-pass-123"})
16377
+ s_v, ov_v, _ = call(vw, "GET", "/api/tutorial")
16378
+ s_vl, les_v, _ = call(vw, "GET", "/api/tutorial/install")
16379
+ s_vd, _, _ = call(vw, "POST", "/api/tutorial/done", {"lesson": "install"})
16380
+ s_v2, ov_v2, _ = call(vw, "GET", "/api/tutorial")
16381
+ s_vh, _, _ = call(vw, "POST", "/api/tutorial/handout", {})
16382
+ s_vp, page_, ph = call(vw, "GET", "/api/tutorial/handout.html", raw_=True)
16383
+ s_404, _, _ = call(vw, "GET", "/api/tutorial/no-such-lesson")
16384
+ op_ = opener_(); call(op_, "POST", "/api/login", {"name": "op", "password": "op-pass-123"})
16385
+ s_oh, oh, _ = call(op_, "POST", "/api/tutorial/handout", {})
16386
+ s_ol, les_o, _ = call(op_, "GET", "/api/tutorial/3")
16387
+ finally:
16388
+ svc.stop()
16389
+ acts = {a["action"] for a in ws.audit_log()}
16390
+ c2 = {
16391
+ "progress": "install" in m1 and "site" in m2 and ov["n_done"] == 2 and ov["next"] == "sign-in" and ov2["n_done"] == 1 and "install" not in TU.progress(ws, "op")
16392
+ and "install" in TU.progress(ws, "viewer") and mark_bad,
16393
+ "handout": hand["lessons"] == len(ls) and all(f'id="l{l["n"]}"' in hh for l in ls) and "<!doctype html>" in hh and hm.count("\n# ") >= len(ls) and "Contents" in hh and "You know it worked when" in hh,
16394
+ "routes": s_anon in (401, 403) and s_v == 200 and ov_v["n_lessons"] == len(ls) and s_vl == 200 and les_v["id"] == "install" and les_v["next"] == "sign-in" and les_v["prev"] is None
16395
+ and "<ol>" in les_v["html"] and s_vd == 200 and ov_v2["n_done"] == 1 and s_vh == 403 and s_oh == 200 and Path(oh["html"]).is_file() and s_404 == 404
16396
+ and s_ol == 200 and les_o["n"] == 3 and les_o["prev"] == "sign-in",
16397
+ "print": s_vp == 200 and b"<!doctype html>" in page_ and "inline" in str(ph.get("Content-Disposition", "")) and f"GEA-Tutorial-{__version__}" in str(ph.get("Content-Disposition", "")),
16398
+ "audit": {"tutorial.handout", "tutorial.print"} <= acts,
16399
+ "tab": "['#/tutorial', 'Tutorial']" in app_src and "VIEWS.tutorial" in app_src and all(t_ in app_src for t_ in ("/api/tutorial/done", "/api/tutorial/handout", "Open the page this lesson is about", "Mark this lesson done", "Print the handout")),
16400
+ "cli": 'add_parser("tutorial"' in main_src and '"--lesson"' in main_src and '"--handout"' in main_src and "TU.write_handout" in main_src,
16401
+ "help": not H.check("tutorial") and any(t_ == "tutorial" for t_, _, _ in H.INDEX) and H.VIEW_TOPIC.get("tutorial") == "tutorial",
16402
+ "ol_render": "<ol>" in H.to_html("1. one\n2. two\n") and "</ol>" in H.to_html("1. one\n2. two\n") and "<ul>" in H.to_html("- a\n- b\n"),
16403
+ }
16404
+ failed2 = [k for k, v in c2.items() if not v]
16405
+ ok(not failed2,
16406
+ "DU2 progress is kept per account (a lesson marked done, by number or by name, and undone; an unknown lesson refused); the handout is written "
16407
+ "whole as HTML and Markdown with every lesson; the routes (anonymous refused; a viewer reads, ticks and prints; writing the handout into the "
16408
+ "workspace takes the operator role; an unknown lesson 404); the audit lines; the Tutorial tab, the tutorial command and the help page carry "
16409
+ "it; numbered steps render as a list" + (f" [failed: {', '.join(failed2)}]" if failed2 else ""))
16410
+
16411
+
16281
16412
  def main() -> int:
16282
16413
  print("GEA-Program - ACCEPTANCE SUITE (the product gate)")
16283
16414
  # a handle a job subprocess still holds at the end must not turn a finished gate into a traceback on Windows:
@@ -16405,6 +16536,7 @@ def main() -> int:
16405
16536
  section_dr_field_recorder(tmp)
16406
16537
  section_ds_updates(tmp)
16407
16538
  section_dt_vpn(tmp)
16539
+ section_du_tutorial(tmp)
16408
16540
  if _FAILS:
16409
16541
  print(f"[ACCEPTANCE] {len(_FAILS)} FAILURES ({_PASS} passed):")
16410
16542
  for f in _FAILS:
@@ -167,6 +167,11 @@ declared extras.
167
167
  addresses; the programs' own sign-in, roles and hashes apply through it
168
168
  unchanged, and the box's page is still bound to the pad network and the
169
169
  tunnel address only.
170
+ - **The tutorial** (since 0.76.0): the lessons are files inside the
171
+ program; reading one writes nothing. A person's ticks are kept in the
172
+ workspace (`records\tutorial_progress.json`, by account name, no more);
173
+ the handout is written only on request into `exports\tutorial\` and
174
+ carries nothing of the site but its name. Both are audit lines.
170
175
 
171
176
  ## What it records
172
177
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  > GEA-Program-Setup: the program installed for you like any Windows program - a window of its own, an icon in the notification area, Start-menu and desktop shortcuts, an Add/Remove Programs entry, upgrades in place - with no administrator rights and the site's data left where it is.
4
4
 
5
- **The command**: download the setup from the release on GitHub (`GEA-Program-Setup-0.75.0.exe` for this version) and run it. It installs for you alone, under `%LOCALAPPDATA%\Programs\GEA-Program`, and asks for the site workspace - the folder that holds the wells, reports, records, accounts and keys. An existing one such as `C:\site` is used exactly as it is, its name included; for a new one (by default `%LOCALAPPDATA%\GEA-Program\site`) it also asks the site's name, which heads every report, and makes the workspace with it (left empty, the workspace is named after its folder; an administrator renames the site in Administration's site settings). Then the Start menu's **GEA-Program** (and the desktop shortcut) starts the control panel when it is not running and opens it in a window of its own. A newer setup installs over the older one: it stops the control panel, replaces the program, keeps the workspace and the choices made before. For a site's software deployment: `GEA-Program-Setup-0.75.0.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /WORKSPACE="C:\site" /SITENAME="Pad 3" /TASKS="desktopicon"` (`/SITENAME` names a workspace the setup makes; one that exists keeps its own name). From a terminal: `gea launch` does what the shortcut does, `gea launch --selftest` says what it would do, `gea tray --selftest` checks the icon.
5
+ **The command**: download the setup from the release on GitHub (`GEA-Program-Setup-0.76.0.exe` for this version) and run it. It installs for you alone, under `%LOCALAPPDATA%\Programs\GEA-Program`, and asks for the site workspace - the folder that holds the wells, reports, records, accounts and keys. An existing one such as `C:\site` is used exactly as it is, its name included; for a new one (by default `%LOCALAPPDATA%\GEA-Program\site`) it also asks the site's name, which heads every report, and makes the workspace with it (left empty, the workspace is named after its folder; an administrator renames the site in Administration's site settings). Then the Start menu's **GEA-Program** (and the desktop shortcut) starts the control panel when it is not running and opens it in a window of its own. A newer setup installs over the older one: it stops the control panel, replaces the program, keeps the workspace and the choices made before. For a site's software deployment: `GEA-Program-Setup-0.76.0.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /WORKSPACE="C:\site" /SITENAME="Pad 3" /TASKS="desktopicon"` (`/SITENAME` names a workspace the setup makes; one that exists keeps its own name). From a terminal: `gea launch` does what the shortcut does, `gea launch --selftest` says what it would do, `gea tray --selftest` checks the icon.
6
6
 
7
7
  **The window**: Microsoft Edge's app window (`msedge --app=`: the control panel with no tabs and no address bar, its own button on the taskbar, which shows the program's derrick and pins as GEA-Program, not as Edge), with a browser profile of its own (`%LOCALAPPDATA%\GEA-Program\window`, no extensions; the first time, Edge may say it signed that profile in to your Microsoft account - Got it), else Google Chrome's, else a tab in the default browser. Where the browser keeps no cookies (its settings or a policy block them), the sign-in page says so and the control panel holds the sign-in itself, in the window's address, until the window is closed. The control panel itself runs with no window of its own: `gea supervise` keeps it running in the background, starts it again when it asks for a restart, and writes everything it would have shown in a console - the start, the sign-ins, the jobs, a stop and why - to `records\console.log` in the workspace. No PowerShell or console window opens. The kit's `start-dashboard.cmd` still runs it in a console window, for a site that wants to watch it there.
8
8
 
@@ -18,7 +18,7 @@
18
18
 
19
19
  **The number to check**: Add/Remove Programs lists GEA-Program with the version you installed; `gea doctor --workspace C:\site` ends with `nothing blocks serving`; the Start menu's **Verify GEA-Program** runs the acceptance gate from the installation and ends with `[ACCEPTANCE] OK - N checks passed`. The release's build installs, upgrades and uninstalls the setup silently before it is published, with the control panel running, and checks the workspace untouched afterwards.
20
20
 
21
- **Signed**: when the publisher's code-signing certificate is configured for the build, the setup is signed with it (Authenticode, timestamped) and Windows names the publisher; until then it ships unsigned and Windows SmartScreen says "unknown publisher" (More info, then Run anyway). The build's provenance holds either way: `gh attestation verify GEA-Program-Setup-0.75.0.exe -R Daniel8Murphy0007/GEA-Program`. The uninstaller the setup leaves behind is Inno Setup's own and is not signed separately.
21
+ **Signed**: when the publisher's code-signing certificate is configured for the build, the setup is signed with it (Authenticode, timestamped) and Windows names the publisher; until then it ships unsigned and Windows SmartScreen says "unknown publisher" (More info, then Run anyway). The build's provenance holds either way: `gh attestation verify GEA-Program-Setup-0.76.0.exe -R Daniel8Murphy0007/GEA-Program`. The uninstaller the setup leaves behind is Inno Setup's own and is not signed separately.
22
22
 
23
23
  **What this page will not call a measurement**: the icon's running or stopped is whether the control panel's port answers on this computer, read every three seconds - not whether every patch, job or report behind it is healthy (Home and the Verification page say that).
24
24
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  **The command**: Reports tab -> Signed dossiers -> **Download GEA Reader for your clients**, or `gea reader --workspace C:\site --out C:\site\GEA-Reader.html`. Send the file once, by any channel (email, a USB stick, the client's portal); send the site's key fingerprint separately - by phone, email or in the contract - as for any dossier. The client opens GEA-Reader.html, drops a dossier on it (or chooses it), and reads the verdict: **Valid** (signed with the site's key, or with a newer key the site's key handed over to), **Valid, but signed by a key you were not given**, or **Not valid** with the reason. Below the verdict: each check, the signer's fingerprint, the key hand-overs, and every file the dossier holds - a report opens in the page as it was signed, a PDF in the browser's own viewer, a table or a log as text, and any file can be saved. A dossier that lists source records by hash without carrying them lets the client choose their copies and checks each against its hash.
6
6
 
7
- **The program**: for a client who wants it installed, **GEA-Reader-Setup-0.75.0.exe** on the release page installs GEA Reader as a Windows program of its own, for the signed-in user, with no administrator rights and nothing of GEA-Program: GEA Reader in the Start menu and on the desktop with its own icon (a white page with a green seal, on blue) and its own taskbar button, and **Check with GEA Reader** on the right-click menu of .zip files (on Windows 11, under Show more options), which opens the dossier at once. It opens the same page in Microsoft Edge's app window with a browser profile of its own (`%LOCALAPPDATA%\GEA-Reader\window`), so a fingerprint the client saves - **Remember this fingerprint**, with whose it is - stays on that computer, and every later dossier signed with that key reads **Valid** with the name the client gave it. `GEA-Reader-portable-0.75.0.zip` is the same program to unzip and run (`GEA-Reader.cmd`). `python\python.exe -m gea_reader --selftest`, in the installed folder, checks the page, the icon, the taskbar identity and the hand-over of a dossier without opening a window.
7
+ **The program**: for a client who wants it installed, **GEA-Reader-Setup-0.76.0.exe** on the release page installs GEA Reader as a Windows program of its own, for the signed-in user, with no administrator rights and nothing of GEA-Program: GEA Reader in the Start menu and on the desktop with its own icon (a white page with a green seal, on blue) and its own taskbar button, and **Check with GEA Reader** on the right-click menu of .zip files (on Windows 11, under Show more options), which opens the dossier at once. It opens the same page in Microsoft Edge's app window with a browser profile of its own (`%LOCALAPPDATA%\GEA-Reader\window`), so a fingerprint the client saves - **Remember this fingerprint**, with whose it is - stays on that computer, and every later dossier signed with that key reads **Valid** with the name the client gave it. `GEA-Reader-portable-0.76.0.zip` is the same program to unzip and run (`GEA-Reader.cmd`). `python\python.exe -m gea_reader --selftest`, in the installed folder, checks the page, the icon, the taskbar identity and the hand-over of a dossier without opening a window.
8
8
 
9
9
  **What it writes**: the one file, GEA-Reader.html (about 40 KB): the checks, written in the page's own script - Ed25519 (RFC 8032) in its own arithmetic, SHA-256 from the browser - and, when made from a workspace, the site's name and the fingerprints of every key it has signed with (the current one and each retired one from the key history: public halves only; the signing key never leaves `keys\`). The audit log records each download (`reader.download`) and each `gea reader` (`reader.write`) with the fingerprints the reader carried. The reader page writes nothing on the client's computer but the fingerprints a client saves (in the browser's storage for the page): it reads the zip it is given, in memory, and a saved copy goes where the client's browser saves downloads. The installed program also writes the page it opens to `%LOCALAPPDATA%\GEA-Reader\page` (with the dossier inside it when one was right-clicked; removed ten minutes later) and its right-click entry under the user's own registry keys, removed with the program.
10
10
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  > GEA Recorder is the program on the pad: a Raspberry Pi in a sealed box that records the ground channels (geophones, accelerometers, electrode dipoles) through a 24-bit ADC and the rig's WITS0 feed, every sample on one GPS-disciplined clock, into hourly miniSEED files with a SHA-256 beside each and a manifest, and serves one status page on the pad network. Nothing to type: power it and it records. GEA pulls its files in and makes stations of them.
4
4
 
5
- **The command**: the **Seismic** tab, the card **Field recorder**: the box's address on the pad network (`http://192.168.1.50:8780` - the status page shows the address) or the folder of the USB mirror carried to the office, a station name if the site's is not wanted, then **Pull** (a job). GEA fetches the manifest, downloads every file it does not have, checks each against its SHA-256, and makes or updates two stations: the array of the ground-motion sensors (band 8-80 Hz, the sensors' positions from the box's config) and the electrode station (0.01-5 Hz); each sensor's hours are joined in order into one record, nothing re-sampled or filtered. Pull again later: only the new hours come across, and the stations are updated in place. From a terminal: `gea workspace --path C:\site --action field-pull --box http://192.168.1.50:8780`. On the box: `gea-recorder status`, `gea-recorder selftest`; `sudo sh kiosk.sh` once puts the live view full-screen on a monitor on the box's HDMI port from boot - RECORDING in green or what is wrong in red, the clock, the rig's depth, every channel's last minute and the ground sensors' spectrogram, nothing to press - and the same view is at `/live` on the box's page from any browser on the pad network; `sudo sh install.sh` once, from the release's `GEA-Recorder-0.75.0.tar.gz`; the box's README has the parts list, the wiring and the three chrony lines for the GPS clock.
5
+ **The command**: the **Seismic** tab, the card **Field recorder**: the box's address on the pad network (`http://192.168.1.50:8780` - the status page shows the address) or the folder of the USB mirror carried to the office, a station name if the site's is not wanted, then **Pull** (a job). GEA fetches the manifest, downloads every file it does not have, checks each against its SHA-256, and makes or updates two stations: the array of the ground-motion sensors (band 8-80 Hz, the sensors' positions from the box's config) and the electrode station (0.01-5 Hz); each sensor's hours are joined in order into one record, nothing re-sampled or filtered. Pull again later: only the new hours come across, and the stations are updated in place. From a terminal: `gea workspace --path C:\site --action field-pull --box http://192.168.1.50:8780`. On the box: `gea-recorder status`, `gea-recorder selftest`; `sudo sh kiosk.sh` once puts the live view full-screen on a monitor on the box's HDMI port from boot - RECORDING in green or what is wrong in red, the clock, the rig's depth, every channel's last minute and the ground sensors' spectrogram, nothing to press - and the same view is at `/live` on the box's page from any browser on the pad network; `sudo sh install.sh` once, from the release's `GEA-Recorder-0.76.0.tar.gz`; the box's README has the parts list, the wiring and the three chrony lines for the GPS clock.
6
6
 
7
7
  **Before there is a Pi**: on the same card, **Start the simulated box**: the recorder's own program runs on this computer with its test signal in place of the ADC (a process of its own, its files under `field\sim-box\` in the workspace, its page on port 8781), **Open its monitor** shows the live screen the attendant will see, **Pull from it** brings its files in as stations, **Stop it** closes every file and lists them. **Open the box's monitor** opens any real box's live screen from its address. The kit and the setup install the recorder's program beside GEA for this; a pip install adds it with `pip install gea-recorder`. **From the office, over the internet**: GEA-VPN (`gea help vpn`, Administration) gives every box a private address the office pulls from (`http://10.77.0.3:8780`) through a tunnel from the pad's cellular modem; the box's zip from that card holds `vpn.sh`, run once on the Pi.
8
8
 
@@ -0,0 +1,26 @@
1
+ # 1. Install GEA on your computer
2
+ Who: office
3
+ Where: #/
4
+ Takes: 15 minutes
5
+ > The program installed like any Windows program, with the site's folder chosen once.
6
+
7
+ ## Before you start
8
+ You need a Windows PC that will stay on while the site is watched (the office machine, or the doghouse PC), and the setup file for this version, `GEA-Program-Setup-0.76.0.exe`, from the release page on GitHub. No administrator rights are needed: the program installs for you alone.
9
+
10
+ ## Steps
11
+ 1. Double-click `GEA-Program-Setup-0.76.0.exe`. If Windows asks whether to run it, choose **Run** - the setup is published by the site, not by a store.
12
+ 2. The setup asks for the **site workspace**: the one folder that will hold the wells, the reports, the records, the accounts and the keys. For a new site keep the default or type `C:\site`. For a workspace that already exists, point at it - it is used exactly as it is, its name included.
13
+ 3. For a new workspace it asks the **site's name** (`Pad 3`). This name heads every report the program writes; an administrator can change it later in Administration, site settings.
14
+ 4. Tick the desktop shortcut and finish. The setup puts **GEA-Program** in the Start menu and an icon in the notification area by the clock.
15
+ 5. Start it: the Start menu's **GEA-Program** or the desktop shortcut. The control panel opens in a window of its own; the first time it asks for the first administrator's name and password (lesson 2).
16
+
17
+ ## What happened on the disk
18
+ The program itself is under your user profile (`%LOCALAPPDATA%\Programs\GEA-Program`); the site is in the workspace folder you chose. Those two never mix: a newer setup replaces the program and leaves the workspace as it is.
19
+
20
+ ## You know it worked when
21
+ The control panel window is open with the site's name in its title, and the notification area shows the GEA icon.
22
+
23
+ ## Common questions
24
+ A newer version: from 0.74.0 the program fetches and installs its own new versions by clicking (lesson 22); you never download a setup again. A second site on the same PC: Administration, **Workspaces**, **Make it and open it** - each site is its own folder and its own window.
25
+
26
+ Help: install, start
@@ -0,0 +1,22 @@
1
+ # 2. Sign in and find your way around
2
+ Who: office
3
+ Where: #/
4
+ Takes: 15 minutes
5
+ > The first account, the four roles, the tabs, the search box, the help panels and the serve window.
6
+
7
+ ## Steps
8
+ 1. The first time the control panel opens it shows **First administrator**: this workspace has no accounts yet. Type a name and a password and press **Create and sign in**; this account is the administrator. Keep the password somewhere safe - nobody can read it back.
9
+ 2. Sign in. The tabs run across the top (on a phone they stack): Home, Control room, Setup, Sites, Wells, Map, 3D, the engineering pages, Seismic, Patch panel, Files, Alarms, Approvals, Configuration, Reports, Verification, Survey, Tools & ports, Catalogue, Rocks, Jobs, Audit / Update, Administration, Tutorial and Help.
10
+ 3. Click **Help** in the top right (the ? button). A short panel appears under the heading of every page saying what it is for, with a **more...** link to the full help page. Leave it on while you learn; turn it off later in your preferences.
11
+ 4. Type a well name or a report name in the **search box** and press Enter: the program finds wells, alarms, reports, jobs, configuration entries, patches and schedules by name.
12
+ 5. Open **Administration**, **Users**, and add one account per person. The **roles**: *viewer* reads everything and changes nothing; *operator* adds wells and data, declares what the operator knows and writes reports; *approver* signs off well tests and approvals; *admin* manages users, settings, backups and the VPN. A person has one role; give the smallest that does the job.
13
+ 6. Look at the window behind the control panel - the **serve window**. It is the server: it prints every sign-in, every job and every stop as it happens. Closing it stops the site; minimise it instead.
14
+ 7. Your own settings are under your name, top right: units (field or SI), your time zone, light or dark, the help panels, your password, and **Sign out everywhere else**.
15
+
16
+ ## You know it worked when
17
+ Every person has an account with the right role, and the Audit / Update tab shows a `user.add` line for each.
18
+
19
+ ## Where things are on the disk
20
+ Everything is in the workspace: `wells\` (one folder per well with its source files and records), `reports\`, `records\audit.jsonl` (the audit log), `users.json`, `keys\` (the signing key and the VPN keys - the backup carries them, nothing else does), `exports\`, `installers\`.
21
+
22
+ Help: start, site
@@ -0,0 +1,22 @@
1
+ # 3. Set up the site
2
+ Who: office
3
+ Where: #/setup
4
+ Takes: 30 minutes
5
+ > The Setup checklist: what the workspace still needs before a report can be handed over, and the site record that holds the wells together.
6
+
7
+ ## Steps
8
+ 1. Open **Setup**. The tab carries a badge with the number of required items still to do, and the Home page says which is next. Each item is done when what it asks for is there, not when someone ticks it.
9
+ 2. **Site name**: as every report will print it. Set it once.
10
+ 3. For each well: the **surface location** (latitude, longitude and the datum the figures are on - NAD27, NAD83 or WGS84, as the permit states), the **reference elevation** (kelly bushing, ground level or derrick floor, in feet, with its source - the completion report, the survey plat), and the **US Well Number** (the API number). With a position declared, **Fetch the ground elevation (USGS 3DEP)** brings the ground elevation there, to check your figure against before declaring.
11
+ 4. **Create the site**: its name (`Retama block`), the client, and the wells it holds. A site is the engagement - what one client has - and the Site Report is the one document for it. The **Sites** tab lists every site with a link to its report.
12
+ 5. The **backup folder**: a folder on another disk or a share (a folder inside the workspace is refused). Press **Back up now** once and **Schedule daily**. Lesson 21 says how to check and restore one.
13
+ 6. **Refresh the reports**: the first run of every report. It is a job; the Jobs tab shows it running and its log.
14
+ 7. Press **Go to the next item** until the badge reads 0. Recommended and optional items are listed beside the required ones; a report can be handed over without them, and says what it cannot say yet.
15
+
16
+ ## You know it worked when
17
+ The Setup badge is gone, the Sites tab lists your site with its client and wells, and the Home page shows the wells with a state each.
18
+
19
+ ## The same from a terminal
20
+ `gea checklist --workspace C:\site` prints the list and exits 0 when every required item is done.
21
+
22
+ Help: setup, sites, site
@@ -0,0 +1,24 @@
1
+ # 4. Add a well from a file
2
+ Who: office
3
+ Where: #/wells
4
+ Takes: 20 minutes
5
+ > A file becomes a well with the same reports as any other: a gauge history, a drilling recorder's export, a well log, a catalogue entry.
6
+
7
+ ## What the program reads
8
+ A CSV from a historian (one timestamp column, then the channels); a drilling recorder's export as the rig delivered it (date and time in two columns, then the WITS channels with -999.25 for what the recorder did not have); a LAS or DLIS well log; a SEG-Y record; an Excel workbook; a table an operator exported. The program detects the layout from the file's first lines and says what it found.
9
+
10
+ ## Steps
11
+ 1. Put the file somewhere the program may read. An administrator names those folders once: Administration, **File roots** - an import root it may read and an export root it may write. `C:\site\_incoming` is a good import root.
12
+ 2. Open **Files**. Browse the import root; beside each file the program says what kind it is (`historian`, `edr`, `las`, `dlis`...). **Preview** shows the first rows as it reads them.
13
+ 3. Press **Import** beside the file, name the well (`Well 30636033`, `SWD-1`) and confirm. The file is copied into the well's folder verbatim and hashed; a file already imported is refused by its hash.
14
+ 4. Open **Wells**. The new well is listed with a state; click it for its page. The first reports are written by **Refresh** (on Home, or the well page): the drilling record for a recorder's export, the drift and quality reports for a gauge history, the strata survey for a log.
15
+ 5. A well from a public dataset: **Wells**, **Add a catalogue well**, choose an entry that carries a downhole gauge series (the Volve production excerpt), name the well inside it and the gauge depth. The Catalogue tab is the map of the 52 datasets the program ships with their provenance.
16
+ 6. For a drilling recorder's well, confirm its **depth events** against the daily drilling reports: on the Setup tab, the item names the well; tick it with a note saying which reports you checked. The well report prints who confirmed them.
17
+
18
+ ## You know it worked when
19
+ The well page shows the file under **Sources** with its SHA-256, and the first report under **Reports**.
20
+
21
+ ## The same from a terminal
22
+ `gea workspace --path C:\site --action add-file --file C:\site\_incoming\30636033.csv --name "Well 30636033"` then `gea workspace --path C:\site --action refresh`.
23
+
24
+ Help: data-in, files, edr, dlis, catalog
@@ -0,0 +1,22 @@
1
+ # 5. A well from its paper records
2
+ Who: office
3
+ Where: #/wells
4
+ Takes: 30 minutes
5
+ > A well known from the regulator's file, the completion report, an inclination survey and an old gas test - entered by clicking, each value kept with the document it came from.
6
+
7
+ ## Steps
8
+ 1. **Wells**, **Add a well from its records**: the well's name and, when you have it, the document - the PDF or the scan of the well file. It is kept verbatim and hashed as the well's source.
9
+ 2. On the well's page the forms come one at a time, each with a **Source** box: name the document and the date it was filed. Fill **Who and where** first - the API number, the operator of record, the position - which puts the well on the Map and on the Operations & seismicity tab.
10
+ 3. **The completion**: the depths, the producing interval, the formation, the nearest lease line.
11
+ 4. **Casing**: a link to the Casing & kick tolerance tab, where each string goes in as for any well (lesson 13).
12
+ 5. **Inclination survey**: the stations one per line as the form writes them - `1289, 1 1/4` for a measured depth and an inclination of one and a quarter degrees. The program checks the depths and the displacement against themselves.
13
+ 6. **Gas well tests**: the shut-in pressure and its depth, the shut-in tubing pressure, the gas gravity, the temperatures, the open flow the document states, and the points one per line: `rate, flowing bottom-hole pressure`. The program fits the deliverability curve and says whether the document's open flow agrees.
14
+ 7. Press **Fill the forms with the worked example** to see a public well file's survey and test in the forms before entering your own; then **Write the records review**.
15
+
16
+ ## You know it worked when
17
+ The records review is under the well's reports, every figure with the document and date it came from, and the well is on the Map.
18
+
19
+ ## A well that is not this site's
20
+ A well you are looking at for someone else belongs in a workspace of its own: Administration, **Workspaces**, **Make it and open it** - it opens in a window of its own with its own port.
21
+
22
+ Help: records
@@ -0,0 +1,19 @@
1
+ # 6. The well page: charts, drift, quality and well tests
2
+ Who: office
3
+ Where: #/wells
4
+ Takes: 30 minutes
5
+ > What the program says about a gauge's record and how to read it.
6
+
7
+ ## Steps
8
+ 1. Open **Wells** and click a well. The page is a stack of cards; each report has a **more...** to its full text and a **save to...** that copies it to the export root.
9
+ 2. **Charts**: choose up to four channels, one per track. Point at the chart for every channel's value at that moment; drag across a stretch to zoom into it; the wheel zooms where you point; double-click shows everything. On a drilling recorder's well the axis switches between **Time** and **Depth**, the depth events are marked where they happened, and each section of recording is a button.
10
+ 3. **Quality**: every sample carries a flag and the rule that set it - GOOD, RANGE (outside the engineering range), ROC (rate of change over the limit), FLATLINE, SPIKE, STALE, GAP. The limits come from the gauge's own datasheet in the gauge library; **Tools & ports** lists them.
11
+ 4. **Drift**: the residual against the well model and the gauge's aging band. The labels mean what they say: *within the band* is not *correct*, and the report says which.
12
+ 5. **Instruments**: a swapped gauge is a new instrument. **Record a swap** (tag, time, old and new serial, certificate id) when one is changed, or **Confirm** a candidate the step detector proposes. **File a certificate** (serial, laboratory, issued, valid until, accuracy, the document); a certificate in its last 60 days raises an alert.
13
+ 6. **Well tests**: stable periods found by the criteria in `criteria.json` (Configuration tab); every rejected period names the rule. A test needs **two approvals** - the Approvals tab lists what is waiting; an approver signs, a second approver signs.
14
+ 7. **Shut-ins and build-ups**: every shut-in in the record gets a first-look build-up analysis. Save the rock and fluid parameters (q, B, mu, h, phi, c_t, r_w) on the card; without them the result is the slope and p* only.
15
+
16
+ ## You know it worked when
17
+ You can point at the chart and name the moment an alarm fired, and the drift card says which band the gauge is in and why.
18
+
19
+ Help: charts, quality, drift, instruments, well-tests, transients
@@ -0,0 +1,20 @@
1
+ # 7. Declarations in one sheet
2
+ Who: office
3
+ Where: #/setup
4
+ Takes: 20 minutes
5
+ > Everything the operator declares about a pad in one spreadsheet, checked against the workspace before anything is written.
6
+
7
+ ## Steps
8
+ 1. On **Setup**, press **Download the sheet**. It is an Excel workbook with one table per subject - who each well is and where, the reference elevation, the day rates and the AFE, the fleet, the drill-string runs, the ESP penetrator and drive, the operation windows and catalogues for Operations & Seismicity, the survey program and plans, the casing program, the torque-and-drag string, the hydraulics, frac stage tables, production and decline terms - already filled with what is declared, with a line above each table saying what it takes.
9
+ 2. Fill in the blanks in Excel. A row names the well it belongs to; a file a row refers to (a survey, a plan, a stage table, a production file, a catalogue export) is named by its file beside the sheet.
10
+ 3. Save it, and on **Setup** press **Check the sheet** and choose it. The program plans every row: **NEW** (nothing declared yet), **CHANGE** (it replaces what is declared - the old value is shown) or **SAME**. One error anywhere and nothing is written; the error names the row and the column.
11
+ 4. With no error, press **Write** (the operator role). Every write is an audit line.
12
+ 5. Import the same sheet again whenever something changes - rows already declared read SAME and are left alone.
13
+
14
+ ## You know it worked when
15
+ The check lists only SAME rows the second time you check the same sheet.
16
+
17
+ ## The same from a terminal
18
+ `gea declare --workspace C:\site --template C:\site\pad3.xlsx` writes the sheet; `gea declare --workspace C:\site --file C:\site\pad3.xlsx` checks it; add `--apply` to write.
19
+
20
+ Help: declare