ldcon 0.2.0__tar.gz → 0.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (796) hide show
  1. {ldcon-0.2.0 → ldcon-0.2.2}/MANIFEST.in +1 -1
  2. {ldcon-0.2.0/src/ldcon.egg-info → ldcon-0.2.2}/PKG-INFO +14 -4
  3. {ldcon-0.2.0 → ldcon-0.2.2}/README.md +13 -3
  4. ldcon-0.2.2/docs/icon.png +0 -0
  5. ldcon-0.2.2/docs/icon.svg +20 -0
  6. ldcon-0.2.2/docs/publishing.html +62 -0
  7. {ldcon-0.2.0 → ldcon-0.2.2}/pyproject.toml +1 -1
  8. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_monitor.py +21 -2
  9. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_task.py +7 -0
  10. ldcon-0.2.2/src/ldcon/agents/dlc_monitor_grant.py +87 -0
  11. ldcon-0.2.2/src/ldcon/agents/dlc_parameter_adjustment.py +274 -0
  12. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/dlc_pi_adjustment.py +7 -3
  13. ldcon-0.2.2/src/ldcon/agents/dlc_pi_plan.py +57 -0
  14. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/monitor_quality_binding.py +3 -2
  15. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/operating_mode_client.py +5 -1
  16. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/adjustment_plan.py +3 -0
  17. ldcon-0.2.2/src/ldcon/jobs/dlc_parameter_measurement.py +87 -0
  18. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/dlc_pi_measurement.py +69 -7
  19. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/dlcpro_cards.py +18 -1
  20. ldcon-0.2.2/src/ldcon/owners/dlcpro_agent_setup.py +43 -0
  21. ldcon-0.2.2/src/ldcon/owners/dlcpro_client_liveness.py +48 -0
  22. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_deployment.py +3 -0
  23. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_ff_delta_adjustment.py +30 -15
  24. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_observation.py +1 -0
  25. ldcon-0.2.2/src/ldcon/owners/dlcpro_operating_mode.py +45 -0
  26. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_owner.py +17 -5
  27. ldcon-0.2.2/src/ldcon/owners/dlcpro_parameter_trial.py +240 -0
  28. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_pi_protocol.py +22 -2
  29. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_pi_trial.py +128 -9
  30. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_service.py +4 -0
  31. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/web_runtime.py +3 -8
  32. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/app.js +2 -1
  33. {ldcon-0.2.0 → ldcon-0.2.2/src/ldcon.egg-info}/PKG-INFO +14 -4
  34. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon.egg-info/SOURCES.txt +16 -0
  35. {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/golden-sr1092.json +7 -0
  36. {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/golden-sr422.json +7 -0
  37. ldcon-0.2.2/tests/test_dlc_adjustment_web.cjs +25 -0
  38. ldcon-0.2.2/tests/test_dlc_monitor_admission.py +98 -0
  39. ldcon-0.2.2/tests/test_dlc_parameter_adjustment.py +310 -0
  40. ldcon-0.2.2/tests/test_dlcpro_agent_setup.py +49 -0
  41. ldcon-0.2.2/tests/test_dlcpro_client_liveness.py +118 -0
  42. ldcon-0.2.2/tests/test_dlcpro_operating_mode.py +235 -0
  43. ldcon-0.2.2/tests/test_dlcpro_parameter_trial.py +198 -0
  44. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_operating_mode_routes.py +7 -2
  45. ldcon-0.2.0/docs/publishing.html +0 -33
  46. ldcon-0.2.0/src/ldcon/agents/dlc_pi_plan.py +0 -24
  47. {ldcon-0.2.0 → ldcon-0.2.2}/.secrets.baseline +0 -0
  48. {ldcon-0.2.0 → ldcon-0.2.2}/LICENSE +0 -0
  49. {ldcon-0.2.0 → ldcon-0.2.2}/package-lock.json +0 -0
  50. {ldcon-0.2.0 → ldcon-0.2.2}/package.json +0 -0
  51. {ldcon-0.2.0 → ldcon-0.2.2}/scripts/check_dist.py +0 -0
  52. {ldcon-0.2.0 → ldcon-0.2.2}/scripts/check_secrets.py +0 -0
  53. {ldcon-0.2.0 → ldcon-0.2.2}/scripts/check_tag.py +0 -0
  54. {ldcon-0.2.0 → ldcon-0.2.2}/scripts/install_wheel.py +0 -0
  55. {ldcon-0.2.0 → ldcon-0.2.2}/setup.cfg +0 -0
  56. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/__init__.py +0 -0
  57. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/_moved.py +0 -0
  58. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agent_tools.py +0 -0
  59. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/__init__.py +0 -0
  60. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/adjustment_guidance.py +0 -0
  61. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/adjustment_quality.py +0 -0
  62. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_adapters.py +0 -0
  63. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_background.py +0 -0
  64. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_bundle.py +0 -0
  65. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_cards.py +0 -0
  66. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_config_access.py +0 -0
  67. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_configuration.py +0 -0
  68. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_configuration_policy.py +0 -0
  69. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_connect.py +0 -0
  70. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_device_parameters.py +0 -0
  71. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_execution.py +0 -0
  72. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_history.py +0 -0
  73. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_inbox_watch.py +0 -0
  74. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_interactive.py +0 -0
  75. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_interactive_hooks.py +0 -0
  76. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_language.py +0 -0
  77. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_log_context.py +0 -0
  78. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_log_read.py +0 -0
  79. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_log_watch.py +0 -0
  80. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_metrics.py +0 -0
  81. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_opencode_http.py +0 -0
  82. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_opencode_mcp.py +0 -0
  83. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_owner_status.py +0 -0
  84. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_profiles.py +0 -0
  85. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_providers.py +0 -0
  86. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_repairs.py +0 -0
  87. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_routing.py +0 -0
  88. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_runtime.py +0 -0
  89. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_sandbox.py +0 -0
  90. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_startup_notice.py +0 -0
  91. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_tools.py +0 -0
  92. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_window.py +0 -0
  93. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_workspace.py +0 -0
  94. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/card_fallback.py +0 -0
  95. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/dlc_pi_response_plan.py +0 -0
  96. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/failure_policy.py +0 -0
  97. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/fallback_service.py +0 -0
  98. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/fallback_targets.py +0 -0
  99. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/gateway_role.py +0 -0
  100. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/manual_adjustment_grant.py +0 -0
  101. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/measurement_grant.py +0 -0
  102. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/notification_policy.py +0 -0
  103. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/report_pdf.py +0 -0
  104. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/resident_adjustment.py +0 -0
  105. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/resident_agent.py +0 -0
  106. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/resident_quality_apply.py +0 -0
  107. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/task_decisions.py +0 -0
  108. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/teams_card.py +0 -0
  109. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/teams_destinations.py +0 -0
  110. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/cld_owner.py +0 -0
  111. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/cli.py +0 -0
  112. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/__init__.py +0 -0
  113. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/adjustment_registry.py +0 -0
  114. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/agent_authority.py +0 -0
  115. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/card_admission.py +0 -0
  116. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/card_definition.py +0 -0
  117. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/card_reporting.py +0 -0
  118. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/configuration.py +0 -0
  119. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/configuration_transaction.py +0 -0
  120. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/contracts.py +0 -0
  121. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/current_settings.py +0 -0
  122. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/deck_yaml.py +0 -0
  123. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/device_conditions.py +0 -0
  124. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/execution_context.py +0 -0
  125. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/instrument_client.py +0 -0
  126. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/interface_cards.py +0 -0
  127. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/interface_schema.py +0 -0
  128. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/laser_assets.py +0 -0
  129. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/metric_quantities.py +0 -0
  130. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/modulation.py +0 -0
  131. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/operation_registry.py +0 -0
  132. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/paths.py +0 -0
  133. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/period_context.py +0 -0
  134. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/records.py +0 -0
  135. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/result_reservations.py +0 -0
  136. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/site_bindings.py +0 -0
  137. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/state_layout.py +0 -0
  138. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/target_policy.py +0 -0
  139. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/telegraf.py +0 -0
  140. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/telemetry.py +0 -0
  141. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/temperature_settings.py +0 -0
  142. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/dashboard_metrics.py +0 -0
  143. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/device_registry.py +0 -0
  144. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/__init__.py +0 -0
  145. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/cld1015.py +0 -0
  146. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/cld1015_config.py +0 -0
  147. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/dlcpro.py +0 -0
  148. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/dlcpro_analog.py +0 -0
  149. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/dlcpro_console.py +0 -0
  150. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/dlcpro_priority.py +0 -0
  151. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/ecdl.py +0 -0
  152. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/esp32_servo.py +0 -0
  153. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/fizeau.py +0 -0
  154. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/frequency_sweep.py +0 -0
  155. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/influx_wavelength.py +0 -0
  156. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/metric_sources.py +0 -0
  157. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/native_dither_telemetry.py +0 -0
  158. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/rigol_scope.py +0 -0
  159. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/siglent.py +0 -0
  160. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/staircase.py +0 -0
  161. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/wsu_udp.py +0 -0
  162. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/esp32_time_telemetry.py +0 -0
  163. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/example_config.py +0 -0
  164. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/fallback_service.py +0 -0
  165. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/instrument_owner.py +0 -0
  166. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/instrument_service.py +0 -0
  167. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/interface_worker.py +0 -0
  168. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/job_service.py +0 -0
  169. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/__init__.py +0 -0
  170. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/adaptive_pid.py +0 -0
  171. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/adaptive_window_session.py +0 -0
  172. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/adjustment_continuation.py +0 -0
  173. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/axis_frequency.py +0 -0
  174. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/axis_frequency_report.py +0 -0
  175. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/background_parameter_session.py +0 -0
  176. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/background_pid_session.py +0 -0
  177. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/branch_maps.py +0 -0
  178. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/branch_target_migration.py +0 -0
  179. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/card_runtime.py +0 -0
  180. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/change_measure.py +0 -0
  181. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/change_measure_adapter.py +0 -0
  182. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/change_measure_dlc.py +0 -0
  183. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/change_measure_parameters.py +0 -0
  184. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/change_measure_target.py +0 -0
  185. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/current_cards.py +0 -0
  186. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/current_devices.py +0 -0
  187. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/dashboard_api.py +0 -0
  188. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/device_parameters.py +0 -0
  189. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/dlcpro_awg_analysis.py +0 -0
  190. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/dlcpro_awg_card.py +0 -0
  191. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_branch_hop.py +0 -0
  192. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_branch_recovery.py +0 -0
  193. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_devices.py +0 -0
  194. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_locked_sweep_proxy.py +0 -0
  195. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_mapped_recovery.py +0 -0
  196. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_mode_map.py +0 -0
  197. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_mode_recovery.py +0 -0
  198. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_online.py +0 -0
  199. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_operating_point.py +0 -0
  200. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_pi_commission.py +0 -0
  201. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_recovery.py +0 -0
  202. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_recovery_plan.py +0 -0
  203. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_recovery_test.py +0 -0
  204. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_relock.py +0 -0
  205. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_response_study.py +0 -0
  206. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_steady.py +0 -0
  207. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_thermal_context.py +0 -0
  208. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_window_center.py +0 -0
  209. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/emission_card.py +0 -0
  210. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/fringe_sweep_reference.py +0 -0
  211. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/interface_devices.py +0 -0
  212. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/interface_worker.py +0 -0
  213. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/job_service.py +0 -0
  214. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/laser_live.py +0 -0
  215. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/learned_settling.py +0 -0
  216. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/lock_target.py +0 -0
  217. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/locked_triangle.py +0 -0
  218. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/measurement_acquisition.py +0 -0
  219. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/measurement_analysis.py +0 -0
  220. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/measurement_execution.py +0 -0
  221. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/measurement_notice.py +0 -0
  222. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/measurement_presets.py +0 -0
  223. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/measurement_report.py +0 -0
  224. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/measurement_statistics.py +0 -0
  225. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/metric_cards.py +0 -0
  226. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/metric_interface.py +0 -0
  227. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/modulation_sweep.py +0 -0
  228. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/native_background_session.py +0 -0
  229. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/native_current_acquire.py +0 -0
  230. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/native_current_card.py +0 -0
  231. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/native_current_online.py +0 -0
  232. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/native_ff_proxy.py +0 -0
  233. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/native_ff_sweep.py +0 -0
  234. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/online_pid.py +0 -0
  235. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/operating_point.py +0 -0
  236. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/operating_point_proxy.py +0 -0
  237. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/operation_execution.py +0 -0
  238. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/operation_history.py +0 -0
  239. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/optical_broker.py +0 -0
  240. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/pi_algorithms.py +0 -0
  241. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/pi_response.py +0 -0
  242. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/progress.py +0 -0
  243. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/quality_baseline.py +0 -0
  244. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/recovery_decisions.py +0 -0
  245. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/recovery_history.py +0 -0
  246. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/recovery_procedure.py +0 -0
  247. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/recovery_reference.py +0 -0
  248. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/recovery_stationary.py +0 -0
  249. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/response_algorithms.py +0 -0
  250. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/response_comparison.py +0 -0
  251. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/response_record.py +0 -0
  252. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/runtime_parameters.py +0 -0
  253. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/settling_profile.py +0 -0
  254. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/shot_analysis.py +0 -0
  255. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/simulation.py +0 -0
  256. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/slow_control.py +0 -0
  257. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/slow_current.py +0 -0
  258. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/study_adoption.py +0 -0
  259. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/study_execution.py +0 -0
  260. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/sweep_ff_analysis.py +0 -0
  261. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/sweep_ff_optimization.py +0 -0
  262. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/sweep_ff_plan.py +0 -0
  263. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/sweep_ff_report.py +0 -0
  264. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/sweep_ff_transport.py +0 -0
  265. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/sweep_tracking.py +0 -0
  266. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/sweep_verdict.py +0 -0
  267. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/target_response.py +0 -0
  268. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/target_response_analysis.py +0 -0
  269. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/target_response_control.py +0 -0
  270. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/target_response_decisions.py +0 -0
  271. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/target_response_experiment.py +0 -0
  272. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/target_response_feedforward.py +0 -0
  273. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/target_response_search.py +0 -0
  274. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/target_response_shift.py +0 -0
  275. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/target_response_thermal.py +0 -0
  276. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/target_response_thermal_experiment.py +0 -0
  277. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/target_sequence.py +0 -0
  278. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/temperature_identification.py +0 -0
  279. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/wavelength_history.py +0 -0
  280. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/window_actions.py +0 -0
  281. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/window_center.py +0 -0
  282. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/window_control.py +0 -0
  283. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/window_decisions.py +0 -0
  284. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/window_sampling.py +0 -0
  285. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/workflow_artifacts.py +0 -0
  286. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/migration/__init__.py +0 -0
  287. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/migration/migration_decks.py +0 -0
  288. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/migration/migration_readiness.py +0 -0
  289. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/migration/migration_relocation.py +0 -0
  290. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/monitor_owner.py +0 -0
  291. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owner_telemetry.py +0 -0
  292. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/__init__.py +0 -0
  293. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/adc_log_threshold.py +0 -0
  294. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/background_grants.py +0 -0
  295. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/cld_instrument_owner.py +0 -0
  296. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/cld_owner.py +0 -0
  297. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/cld_projection.py +0 -0
  298. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/cld_system_owner.py +0 -0
  299. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/current_owner.py +0 -0
  300. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/device_registry.py +0 -0
  301. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_awg_plan.py +0 -0
  302. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_awg_port.py +0 -0
  303. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_awg_protocol.py +0 -0
  304. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_awg_return.py +0 -0
  305. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_awg_sweep.py +0 -0
  306. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_awg_timing.py +0 -0
  307. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_awg_tracking.py +0 -0
  308. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_awg_tracking_guard.py +0 -0
  309. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_awg_tracking_report.py +0 -0
  310. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_awg_zero.py +0 -0
  311. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_ff.py +0 -0
  312. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_ff_adjustment.py +0 -0
  313. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_frequency_window.py +0 -0
  314. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_readback.py +0 -0
  315. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_target_changes.py +0 -0
  316. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_target_step.py +0 -0
  317. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_target_store.py +0 -0
  318. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_telemetry.py +0 -0
  319. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_background_parameters.py +0 -0
  320. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_background_pid.py +0 -0
  321. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_hot_control.py +0 -0
  322. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_independent_pid.py +0 -0
  323. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_locked_study.py +0 -0
  324. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_locked_sweep.py +0 -0
  325. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_native_pid.py +0 -0
  326. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_optical.py +0 -0
  327. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_owner.py +0 -0
  328. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_policy_reload.py +0 -0
  329. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_prelock.py +0 -0
  330. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_projection.py +0 -0
  331. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_steady_owner.py +0 -0
  332. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_steady_policy.py +0 -0
  333. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_target_ff.py +0 -0
  334. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_target_settling.py +0 -0
  335. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_tec_pair.py +0 -0
  336. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_thermal_study.py +0 -0
  337. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/emission.py +0 -0
  338. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/emission_adapters.py +0 -0
  339. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/esp32_native_client.py +0 -0
  340. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/esp32_native_owner.py +0 -0
  341. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/esp32_time_telemetry.py +0 -0
  342. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/esp32_udp_gate.py +0 -0
  343. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/external_sweep_guard.py +0 -0
  344. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/flexible_native_trial.py +0 -0
  345. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/fringe_peaks.py +0 -0
  346. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/full_data_log.py +0 -0
  347. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/instrument_identity.py +0 -0
  348. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/instrument_owner.py +0 -0
  349. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/instrument_projection.py +0 -0
  350. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/instrument_service.py +0 -0
  351. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/migration_physical_lock.py +0 -0
  352. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/monitor_owner.py +0 -0
  353. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/native_assembly.py +0 -0
  354. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/native_assembly_host.py +0 -0
  355. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/native_background.py +0 -0
  356. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/native_current_tuning.py +0 -0
  357. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/native_ff_proof.py +0 -0
  358. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/native_instrument_owner.py +0 -0
  359. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/native_modulation_limits.py +0 -0
  360. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/native_policy_reload.py +0 -0
  361. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/native_policy_safety.py +0 -0
  362. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/native_policy_update.py +0 -0
  363. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/native_system_owner.py +0 -0
  364. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/operating_mode_owner.py +0 -0
  365. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/owner_projection.py +0 -0
  366. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/owner_telemetry.py +0 -0
  367. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/pi_handover.py +0 -0
  368. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/projection_transport.py +0 -0
  369. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/remote_instruments.py +0 -0
  370. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/sdg_client.py +0 -0
  371. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/sdg_owner.py +0 -0
  372. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/tec_rate.py +0 -0
  373. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/wsu_udp_monitor.py +0 -0
  374. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/report_pdf.py +0 -0
  375. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/agent-model-options.json +0 -0
  376. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/agent_contract/adjustment.txt +0 -0
  377. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/agent_contract/common.txt +0 -0
  378. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/agent_contract/diagnosis.txt +0 -0
  379. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/agent_contract/research.txt +0 -0
  380. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/agent_contract/response_optimization.txt +0 -0
  381. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/examples/README.html +0 -0
  382. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/examples/assignments/sr1092.yaml +0 -0
  383. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/examples/assignments/sr422.yaml +0 -0
  384. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/examples/assignments/thf685.yaml +0 -0
  385. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/examples/interface-decks/dfb-dbr-ldc-tec.yaml +0 -0
  386. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/examples/interface-decks/ecdl-dlcpro.yaml +0 -0
  387. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/examples/interface-decks/ecdl-pzt-ldc-tec.yaml +0 -0
  388. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/examples/lasers/sr1092.yaml +0 -0
  389. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/examples/lasers/sr422.yaml +0 -0
  390. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/examples/lasers/thf685.yaml +0 -0
  391. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/report_template/ldconreport.cls +0 -0
  392. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/report_template/report.tex +0 -0
  393. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/__init__.py +0 -0
  394. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/agent_approval_api.py +0 -0
  395. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/agent_settings_api.py +0 -0
  396. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/agent_task_api.py +0 -0
  397. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/control_readback.py +0 -0
  398. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/dashboard_activity.py +0 -0
  399. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/dashboard_controls_revision.py +0 -0
  400. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/dashboard_metrics.py +0 -0
  401. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/dashboard_snapshot.py +0 -0
  402. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/dashboard_state.py +0 -0
  403. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/dashboard_wavelength.py +0 -0
  404. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/device_parameters_api.py +0 -0
  405. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/dither_quality.py +0 -0
  406. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/dlcpro_target_api.py +0 -0
  407. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/dlcpro_target_query.py +0 -0
  408. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/failure_api.py +0 -0
  409. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/gateway_lan.py +0 -0
  410. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/grafana_activity.py +0 -0
  411. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/grafana_dashboard.py +0 -0
  412. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/grafana_dlcpro.py +0 -0
  413. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/grafana_quality.py +0 -0
  414. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/interface_projection.py +0 -0
  415. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/job_registry.py +0 -0
  416. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/job_report.py +0 -0
  417. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/laser_operations.py +0 -0
  418. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/lock_target_api.py +0 -0
  419. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/lock_target_queue.py +0 -0
  420. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/log_archive.py +0 -0
  421. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/metric_query_profiles.py +0 -0
  422. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/online_position.py +0 -0
  423. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/operating_mode_api.py +0 -0
  424. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/operation_api.py +0 -0
  425. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/operation_observation.py +0 -0
  426. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/operations_settings.py +0 -0
  427. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/quality_threshold_metrics.py +0 -0
  428. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/shot_analysis_api.py +0 -0
  429. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/sweep_api.py +0 -0
  430. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/sweep_guard.py +0 -0
  431. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/target_reference_panel.py +0 -0
  432. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/teams_destinations_api.py +0 -0
  433. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/web_fleet.py +0 -0
  434. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/web_server.py +0 -0
  435. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/window_api.py +0 -0
  436. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/agent-settings.css +0 -0
  437. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/agent-settings.html +0 -0
  438. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/agent-settings.js +0 -0
  439. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/app.css +0 -0
  440. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/card-browser.js +0 -0
  441. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/card-guide.js +0 -0
  442. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/acquire.metrics.html +0 -0
  443. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/agent.history_review.html +0 -0
  444. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/agent.log_watch.html +0 -0
  445. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/agent.monitor.html +0 -0
  446. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/agent.request.html +0 -0
  447. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/agent.resident.html +0 -0
  448. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/agent.task.html +0 -0
  449. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/commission.ecdl_pi.html +0 -0
  450. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/identify.axis_frequency.html +0 -0
  451. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/identify.current_response.html +0 -0
  452. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/laser.emission.html +0 -0
  453. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/measure.batch.html +0 -0
  454. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/measure.change.html +0 -0
  455. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/measure.target_response.html +0 -0
  456. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/monitor.wavelength.html +0 -0
  457. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/notify.teams.html +0 -0
  458. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/optimize.settling_criteria.html +0 -0
  459. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/optimize.target_feedforward.html +0 -0
  460. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/optimize.target_step.html +0 -0
  461. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/optimize.target_thermal.html +0 -0
  462. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/plan.ecdl_recovery.html +0 -0
  463. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/prepare.ecdl_recovery.html +0 -0
  464. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/recover.ecdl_mode_hop.html +0 -0
  465. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/report.grafana_dashboard.html +0 -0
  466. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/servo.current_pid.html +0 -0
  467. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/servo.dlcpro_frequency.html +0 -0
  468. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/servo.ecdl_steady_lock.html +0 -0
  469. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/servo.native_current.html +0 -0
  470. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/study.ecdl_current_response.html +0 -0
  471. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/study.ecdl_locked_current_map.html +0 -0
  472. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/study.ecdl_mode_map.html +0 -0
  473. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/study.ecdl_thermal_context.html +0 -0
  474. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/study.target_response.html +0 -0
  475. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/sweep.current_modulation.html +0 -0
  476. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/sweep.dlcpro_frequency.html +0 -0
  477. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/sweep.servo_modulation.html +0 -0
  478. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/test.ecdl_recovery.html +0 -0
  479. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/tune.ecdl_initial_point.html +0 -0
  480. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/tune.ecdl_operating_point.html +0 -0
  481. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/tune.ecdl_window_center.html +0 -0
  482. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/tune.native_current.html +0 -0
  483. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/tune.pid_coordinate_search.html +0 -0
  484. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/tune.pid_factor_reduction.html +0 -0
  485. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/tune.pid_online.html +0 -0
  486. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/tune.temperature_once.html +0 -0
  487. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/committing-input.js +0 -0
  488. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/configuration-editor.js +0 -0
  489. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/dashboard-state.js +0 -0
  490. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/failures.html +0 -0
  491. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/failures.js +0 -0
  492. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/fallback.css +0 -0
  493. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/fallback.html +0 -0
  494. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/fallback.js +0 -0
  495. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/fleet-settings.js +0 -0
  496. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/fleet.css +0 -0
  497. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/fleet.html +0 -0
  498. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/fleet.js +0 -0
  499. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/gateway-presentation.js +0 -0
  500. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/grafana-help.js +0 -0
  501. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/help.html +0 -0
  502. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/i18n.js +0 -0
  503. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/index.html +0 -0
  504. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/laser-workspace.js +0 -0
  505. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/modulation.html +0 -0
  506. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/modulation.js +0 -0
  507. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/reservations.html +0 -0
  508. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/reservations.js +0 -0
  509. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/teams-settings.js +0 -0
  510. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/window-actions.js +0 -0
  511. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/workspace.css +0 -0
  512. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_fleet.py +0 -0
  513. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_server.py +0 -0
  514. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon.egg-info/dependency_links.txt +0 -0
  515. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon.egg-info/entry_points.txt +0 -0
  516. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon.egg-info/requires.txt +0 -0
  517. {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon.egg-info/top_level.txt +0 -0
  518. {ldcon-0.2.0 → ldcon-0.2.2}/tests/__init__.py +0 -0
  519. {ldcon-0.2.0 → ldcon-0.2.2}/tests/conftest.py +0 -0
  520. {ldcon-0.2.0 → ldcon-0.2.2}/tests/dashboard_fixture.cjs +0 -0
  521. {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/dlcpro-fw19.json +0 -0
  522. {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/var/device-owners/cld1015-M01343851/config.json +0 -0
  523. {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/var/device-owners/esp32servocon-sr1092/config.json +0 -0
  524. {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/var/device-owners/scope-sr422-sr1092/config.json +0 -0
  525. {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/var/device-owners/sr422/config.json +0 -0
  526. {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/var/instrument-owners/bk4054b-51524H117/config.json +0 -0
  527. {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/var/instrument-owners/sdg2042x-SDG2XFBCA00839/config.json +0 -0
  528. {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/var/instrument-owners/sdg2042x-SDG2XFBCA00845/config.json +0 -0
  529. {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/var/lasers/sr1092/config/assignments/sr1092.yaml +0 -0
  530. {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/var/lasers/sr1092/config/interface-decks/dfb-dbr-ldc-tec.yaml +0 -0
  531. {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/var/lasers/sr1092/config/lasers/sr1092.yaml +0 -0
  532. {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/var/lasers/sr1092/laser-layout.json +0 -0
  533. {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/var/lasers/sr422/config/assignments/sr422.yaml +0 -0
  534. {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/var/lasers/sr422/config/interface-decks/ecdl-pzt-ldc-tec.yaml +0 -0
  535. {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/var/lasers/sr422/config/lasers/sr422.yaml +0 -0
  536. {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/var/lasers/sr422/laser-layout.json +0 -0
  537. {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/entry-startup/assembly-definition.yaml +0 -0
  538. {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/entry-startup/sr1092-broker.yaml +0 -0
  539. {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/pi-handover-v1.json +0 -0
  540. {ldcon-0.2.0 → ldcon-0.2.2}/tests/legacy_mapped_recovery_fixture.py +0 -0
  541. {ldcon-0.2.0 → ldcon-0.2.2}/tests/legacy_rearm_trim_fixture.py +0 -0
  542. {ldcon-0.2.0 → ldcon-0.2.2}/tests/legacy_recovery_executor_fixture.py +0 -0
  543. {ldcon-0.2.0 → ldcon-0.2.2}/tests/legacy_recovery_plan_fixture.py +0 -0
  544. {ldcon-0.2.0 → ldcon-0.2.2}/tests/legacy_recovery_test_fixture.py +0 -0
  545. {ldcon-0.2.0 → ldcon-0.2.2}/tests/measurement_fixtures.py +0 -0
  546. {ldcon-0.2.0 → ldcon-0.2.2}/tests/recovery_legacy_fixtures.py +0 -0
  547. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/examples/dlcpro/assignment.yaml +0 -0
  548. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/examples/dlcpro/deck.yaml +0 -0
  549. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/examples/dlcpro/existing-ecdl-calibration.yaml +0 -0
  550. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/examples/dlcpro/laser.offline.yaml +0 -0
  551. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/examples/dlcpro/owner.offline.json +0 -0
  552. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/examples/dlcpro/pi-agent-cards.yaml +0 -0
  553. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/examples/dlcpro/thf685/laser.yaml +0 -0
  554. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/examples/dlcpro/thf685/owner.json +0 -0
  555. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/examples/measurement-decks/dfb-dbr-ldc-tec.yaml +0 -0
  556. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/examples/measurement-decks/ecdl-pzt-ldc-tec.yaml +0 -0
  557. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/examples/interface-config/assignments/sr1092.yaml +0 -0
  558. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/examples/interface-config/assignments/sr422.yaml +0 -0
  559. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/examples/interface-config/interface-decks/dfb-dbr-ldc-tec.yaml +0 -0
  560. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/examples/interface-config/interface-decks/ecdl-pzt-ldc-tec.yaml +0 -0
  561. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/examples/interface-config/lasers/sr1092.yaml +0 -0
  562. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/examples/interface-config/lasers/sr422.yaml +0 -0
  563. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/tests/fixtures/live-20261022/assignments/sr1092.yaml +0 -0
  564. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/tests/fixtures/live-20261022/assignments/sr422.yaml +0 -0
  565. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/tests/fixtures/live-20261022/interface-decks/dfb-dbr-ldc-tec.yaml +0 -0
  566. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/tests/fixtures/live-20261022/interface-decks/ecdl-pzt-ldc-tec.yaml +0 -0
  567. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/tests/fixtures/live-20261022/lasers/sr1092.yaml +0 -0
  568. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/tests/fixtures/live-20261022/lasers/sr422.yaml +0 -0
  569. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/tests/test_esp32_native_current.py +0 -0
  570. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/tests/test_lock_target.py +0 -0
  571. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/tests/test_native_ff_owner.py +0 -0
  572. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/tests/test_native_live_moves.py +0 -0
  573. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/ops/effective_settings.py +0 -0
  574. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/ops/inspect_dlcpro.py +0 -0
  575. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/ops/prepare_pi_handover.py +0 -0
  576. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/ops/trim_owner_config.py +0 -0
  577. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/ops/update_pi_handover.py +0 -0
  578. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/owner/tests/fake_projection.py +0 -0
  579. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/owner/tests/fake_rig.py +0 -0
  580. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/owner/tests/locked_sweep_settings.yaml +0 -0
  581. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/owner/tests/test_background_pid_owner.py +0 -0
  582. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/owner/tests/test_locked_sweep_owner.py +0 -0
  583. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/scripts/monitor_configuration.py +0 -0
  584. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/scripts/test_live_background_handoff.py +0 -0
  585. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/tests/test_ecdl_acquisition_gate_fixes.py +0 -0
  586. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/tests/test_learned_settling.py +0 -0
  587. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/web/examples/interface-config/assignments/sr1092.yaml +0 -0
  588. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/web/examples/interface-config/assignments/sr422.yaml +0 -0
  589. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/web/examples/interface-config/interface-decks/dfb-dbr-ldc-tec.yaml +0 -0
  590. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/web/examples/interface-config/interface-decks/ecdl-pzt-ldc-tec.yaml +0 -0
  591. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/web/examples/interface-config/lasers/sr1092.yaml +0 -0
  592. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/web/examples/interface-config/lasers/sr422.yaml +0 -0
  593. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/web/tests/fixtures/live-20261022/assignments/sr1092.yaml +0 -0
  594. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/web/tests/fixtures/live-20261022/assignments/sr422.yaml +0 -0
  595. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/web/tests/fixtures/live-20261022/interface-decks/dfb-dbr-ldc-tec.yaml +0 -0
  596. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/web/tests/fixtures/live-20261022/interface-decks/ecdl-pzt-ldc-tec.yaml +0 -0
  597. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/web/tests/fixtures/live-20261022/lasers/sr1092.yaml +0 -0
  598. {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/web/tests/fixtures/live-20261022/lasers/sr422.yaml +0 -0
  599. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_adaptive_window_session.py +0 -0
  600. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_adjustment_continuation.py +0 -0
  601. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_adjustment_guidance.py +0 -0
  602. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_adjustment_guidance_web.cjs +0 -0
  603. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_adjustment_quality.py +0 -0
  604. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_adopt_after_prewrite_reject_20261028.py +0 -0
  605. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_agent_background_gateway.py +0 -0
  606. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_agent_difficulty_routing.py +0 -0
  607. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_agent_host_integration.py +0 -0
  608. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_agent_model_negotiation.py +0 -0
  609. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_agent_monitor_history.py +0 -0
  610. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_agent_providers.py +0 -0
  611. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_agent_routing_layout.cjs +0 -0
  612. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_agent_settings_api.py +0 -0
  613. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_agent_settings_ui.cjs +0 -0
  614. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_agent_task_tool_arguments.py +0 -0
  615. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_agent_tasks.py +0 -0
  616. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_approval_layout_owner.py +0 -0
  617. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_background_foreground_native_matrix.py +0 -0
  618. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_background_start_observation.py +0 -0
  619. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_background_window_session.py +0 -0
  620. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_card_browser_assets.py +0 -0
  621. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_card_browser_ui.cjs +0 -0
  622. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_card_readiness.cjs +0 -0
  623. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_card_start_reasons.cjs +0 -0
  624. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_change_measure.py +0 -0
  625. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_change_measure_adapter.py +0 -0
  626. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_change_measure_dlc.py +0 -0
  627. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_change_measure_target.py +0 -0
  628. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_claude_interactive_metadata.py +0 -0
  629. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_claude_profile_transport.py +0 -0
  630. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_cld_system_boundary.py +0 -0
  631. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_committing_input.cjs +0 -0
  632. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_config_two_layer_step34.py +0 -0
  633. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_configuration_numeric_roundtrip.py +0 -0
  634. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_configuration_review_refresh.cjs +0 -0
  635. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_controller_status_projection.py +0 -0
  636. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dashboard_activity.py +0 -0
  637. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dashboard_polish.py +0 -0
  638. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dashboard_workspace.cjs +0 -0
  639. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_decision_progress_prefix.py +0 -0
  640. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_display_state_consistency.cjs +0 -0
  641. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dither_pause_20261027.py +0 -0
  642. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dither_quality_review_20261028.py +0 -0
  643. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dither_review_aggregation_20261028.py +0 -0
  644. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlc_pi_adjustment.py +0 -0
  645. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlc_pi_target_steps.py +0 -0
  646. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlc_response_policy.py +0 -0
  647. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlc_trace_state.py +0 -0
  648. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_adc_authority.py +0 -0
  649. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_awg.py +0 -0
  650. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_awg_async.py +0 -0
  651. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_awg_card.py +0 -0
  652. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_awg_enable.py +0 -0
  653. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_awg_identity.py +0 -0
  654. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_awg_protocol.py +0 -0
  655. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_awg_return.py +0 -0
  656. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_awg_tracking.py +0 -0
  657. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_awg_tracking_failures.py +0 -0
  658. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_awg_tracking_guard.py +0 -0
  659. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_awg_zero.py +0 -0
  660. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_console.py +0 -0
  661. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_fast_servo.py +0 -0
  662. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_ff_adjustment.py +0 -0
  663. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_ff_delta_adjustment.py +0 -0
  664. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_frequency_window.py +0 -0
  665. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_grafana.py +0 -0
  666. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_lock_input_window.py +0 -0
  667. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_native_scan_frequency.py +0 -0
  668. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_offline.py +0 -0
  669. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_pi_trial.py +0 -0
  670. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_target_api.py +0 -0
  671. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_target_api_fleet.py +0 -0
  672. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_target_api_routing.py +0 -0
  673. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_telemetry.py +0 -0
  674. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_tracking_io_budget.py +0 -0
  675. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_tracking_timing_io.py +0 -0
  676. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_udp.py +0 -0
  677. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_ecdl_branch_hop.py +0 -0
  678. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_ecdl_independent_pid.py +0 -0
  679. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_ecdl_ldc_target_ff.py +0 -0
  680. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_ecdl_owner_readopt.py +0 -0
  681. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_ecdl_owner_startup_adoption.py +0 -0
  682. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_ecdl_ready_target.py +0 -0
  683. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_ecdl_rearm_trim.py +0 -0
  684. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_ecdl_recovery_card.py +0 -0
  685. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_ecdl_settings_adopt.py +0 -0
  686. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_ecdl_target_settling.py +0 -0
  687. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_ecdl_tec_alignment_approach.py +0 -0
  688. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_effective_settings.py +0 -0
  689. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_emission.py +0 -0
  690. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_emission_native.py +0 -0
  691. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_entry_startup.py +0 -0
  692. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_failure_review.cjs +0 -0
  693. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_fleet_pdf_reports.py +0 -0
  694. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_gateway_defaults_ui.cjs +0 -0
  695. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_gateway_lan.py +0 -0
  696. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_gateway_notifications.py +0 -0
  697. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_gateway_presentation.cjs +0 -0
  698. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_gateway_presentation.py +0 -0
  699. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_http_request_ids.cjs +0 -0
  700. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_job_report.py +0 -0
  701. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_legacy_broker_projection.py +0 -0
  702. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_live_control_bulk.cjs +0 -0
  703. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_lock_target_correlation.py +0 -0
  704. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_measurement_acquisition.py +0 -0
  705. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_measurement_execution_integration.py +0 -0
  706. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_measurement_parameter_transactions.py +0 -0
  707. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_measurement_plan_authority.py +0 -0
  708. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_measurement_presets.py +0 -0
  709. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_midpoint_pilot.py +0 -0
  710. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_monitor_readback.py +0 -0
  711. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_moved_modules.py +0 -0
  712. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_native_assembly_adoption.py +0 -0
  713. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_native_background.py +0 -0
  714. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_native_integral_hotload.py +0 -0
  715. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_native_modulation_limits.py +0 -0
  716. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_native_owner_readopt.py +0 -0
  717. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_native_post_retarget_recentre.py +0 -0
  718. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_native_system_boundary.py +0 -0
  719. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_native_target_policy_update.py +0 -0
  720. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_notification_policy.py +0 -0
  721. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_opencode_mcp_lifetime.py +0 -0
  722. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_opencode_notification_queue.py +0 -0
  723. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_opencode_shared.py +0 -0
  724. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_operating_guidance_fleet.py +0 -0
  725. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_operating_mode_owner.py +0 -0
  726. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_operating_point_latency.py +0 -0
  727. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_operating_point_readback_failure.py +0 -0
  728. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_operation_execution.py +0 -0
  729. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_operation_gateway.py +0 -0
  730. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_operation_history.py +0 -0
  731. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_operation_observation.py +0 -0
  732. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_operation_record_delivery.py +0 -0
  733. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_owner_projection.py +0 -0
  734. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_package_boundary.py +0 -0
  735. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_parameter_workspace.cjs +0 -0
  736. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_pi_algorithm_identity.py +0 -0
  737. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_pi_public_retirement.py +0 -0
  738. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_pi_release_update.py +0 -0
  739. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_pi_response_workflow.py +0 -0
  740. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_pi_trial_envelope_20261028.py +0 -0
  741. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_preflight_reference_resolution.py +0 -0
  742. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_projection_transport.py +0 -0
  743. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_public_examples.py +0 -0
  744. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_quality_baseline.py +0 -0
  745. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_quality_baseline_hooks.py +0 -0
  746. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_quality_report_only.py +0 -0
  747. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_quality_threshold_layout.py +0 -0
  748. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_recovery_decisions.py +0 -0
  749. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_recovery_explicit_policy.py +0 -0
  750. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_recovery_history.py +0 -0
  751. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_recovery_reference_v2.py +0 -0
  752. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_recovery_without_map_lookup.py +0 -0
  753. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_refresh_layout.cjs +0 -0
  754. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_report_policy.py +0 -0
  755. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_resident_adjustment.py +0 -0
  756. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_resident_adjustment_web.cjs +0 -0
  757. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_resident_quality_apply.py +0 -0
  758. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_response_algorithm_integration.py +0 -0
  759. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_response_comparison.py +0 -0
  760. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_rollout_site_boundaries.py +0 -0
  761. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_settling_profile_consumer.py +0 -0
  762. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_single_laser_layout.py +0 -0
  763. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_stationary_unlimited_recovery.py +0 -0
  764. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_steady_planner_hold_only.py +0 -0
  765. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_steady_recovery_retirement.py +0 -0
  766. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_study_adoption.py +0 -0
  767. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_study_execution.py +0 -0
  768. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_study_history_display.py +0 -0
  769. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_sweep_admission.py +0 -0
  770. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_sweep_ff_analysis.py +0 -0
  771. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_sweep_ff_optimization.py +0 -0
  772. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_sweep_ff_report.py +0 -0
  773. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_sweep_ff_transport.py +0 -0
  774. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_target_cancel_ui.cjs +0 -0
  775. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_target_feedforward.py +0 -0
  776. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_target_ff_completion.py +0 -0
  777. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_target_response.py +0 -0
  778. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_target_response_control.py +0 -0
  779. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_target_response_experiment.py +0 -0
  780. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_target_response_feedforward.py +0 -0
  781. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_target_response_search.py +0 -0
  782. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_target_response_shift.py +0 -0
  783. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_target_response_web.cjs +0 -0
  784. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_target_sequence.py +0 -0
  785. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_target_step_authority.py +0 -0
  786. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_target_text_formats.py +0 -0
  787. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_task_decisions.py +0 -0
  788. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_task_profile_ui.cjs +0 -0
  789. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_teams_destinations.py +0 -0
  790. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_teams_settings_ui.cjs +0 -0
  791. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_unified_quality.py +0 -0
  792. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_window_hop_boundary_20261027.py +0 -0
  793. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_window_observable_selection.py +0 -0
  794. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_workspace_inventory.py +0 -0
  795. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_workspace_selector.cjs +0 -0
  796. {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_wsu_udp_monitor.py +0 -0
@@ -1,5 +1,5 @@
1
1
  include LICENSE README.md
2
- recursive-include docs *.html
2
+ recursive-include docs *.html *.svg *.png
3
3
  recursive-include scripts *.py
4
4
  recursive-include tests *.py *.cjs *.json *.yaml
5
5
  recursive-include examples *.json
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ldcon
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: Laser operations, physical owners and fleet presentation
5
5
  Author: FanHarvard contributors
6
6
  License-Expression: MIT
@@ -38,12 +38,14 @@ Provides-Extra: analysis
38
38
  Requires-Dist: scipy>=1.10; extra == "analysis"
39
39
  Dynamic: license-file
40
40
 
41
+ <img src="https://raw.githubusercontent.com/FanHarvard/ldcon/main/docs/icon.png" alt="LDCon: an agent guiding a laser feedback loop" width="64" height="64">
42
+
41
43
  # LDCon
42
44
 
43
45
  **Still in active development.**
44
46
 
45
47
  Laser locking, characterization and a Web dashboard. **ECDL and DFB/DBR control
46
- are implemented**, including ESP32-based native PI and TOPTICA DLCpro adapters.
48
+ are implemented**, with digital-servo PI control and TOPTICA DLCpro adapters.
47
49
 
48
50
  ```sh
49
51
  pip install "ldcon[web,instruments,analysis]"
@@ -55,6 +57,9 @@ Python 3.10+ on Linux. `experiment-core` installs automatically. Optional agent
55
57
  messaging: `pip install "ldcon[agents]"` (installs `fanharvard-agentbridge`).
56
58
  Provider CLIs and their authentication are separate.
57
59
 
60
+ Supported agent interfaces: **Claude Code, Codex and OpenCode**, with a DeepSeek
61
+ Harness adapter for card tasks.
62
+
58
63
  **Agents** monitor results, diagnose problems and run bounded characterization,
59
64
  parameter tuning and recovery through registered control cards. **Humans** choose
60
65
  the experiment, target, hardware configuration and physical safety limits, and
@@ -69,11 +74,14 @@ Missing data remains unknown; quality labels are distinct from physical safety.
69
74
 
70
75
  | Configuration | Hardware |
71
76
  | --- | --- |
72
- | ECDL / ESP32 | Wavemeter and data feed, ESP32 servo DAC/firmware, piezo driver, current/TEC controllers and supported AWGs (e.g. Siglent SDG) |
73
- | DFB/DBR | Wavemeter, current/TEC controller (e.g. Thorlabs CLD1015); ESP32 DAC and modulation input for native current PI |
77
+ | ECDL / digital servo | Wavemeter and data feed, compatible digital servo/DAC, piezo driver, current/TEC controllers and supported AWGs (e.g. Siglent SDG) |
78
+ | DFB/DBR | Wavemeter, current/TEC controller (e.g. Thorlabs CLD1015); compatible digital servo/DAC and modulation input for native current PI |
74
79
  | ECDL / DLCpro | TOPTICA DLCpro, wavemeter feedback; AWG/trigger connections for configured feedforward scans |
75
80
  | Spectral quality / studies | Fringe image source for secondary-peak analysis; scope/telemetry and AWG where required by the selected measurement |
76
81
 
82
+ For digital-servo hardware and integration details, please contact
83
+ [kenjishu@fas.harvard.edu](mailto:kenjishu@fas.harvard.edu).
84
+
77
85
  Tests use simulations, fake instruments and loopback services to cover control
78
86
  contracts, owner exclusivity, uncertain writes, cancellation/recovery, tuning,
79
87
  sweeps, configuration, quality reporting and Web behavior. They do not certify
@@ -83,3 +91,5 @@ a new physical setup. See [test suite](tests/).
83
91
  laser definitions, decks and assignments, with output disabled and placeholder
84
92
  connections. Installation starts no hardware or service and includes no credentials.
85
93
  [Publishing](docs/publishing.html) · [MIT license](LICENSE)
94
+
95
+ FanHarvard site configuration and deployment: [ldcon-fanharvard](https://github.com/FanHarvard/ldcon-fanharvard).
@@ -1,9 +1,11 @@
1
+ <img src="https://raw.githubusercontent.com/FanHarvard/ldcon/main/docs/icon.png" alt="LDCon: an agent guiding a laser feedback loop" width="64" height="64">
2
+
1
3
  # LDCon
2
4
 
3
5
  **Still in active development.**
4
6
 
5
7
  Laser locking, characterization and a Web dashboard. **ECDL and DFB/DBR control
6
- are implemented**, including ESP32-based native PI and TOPTICA DLCpro adapters.
8
+ are implemented**, with digital-servo PI control and TOPTICA DLCpro adapters.
7
9
 
8
10
  ```sh
9
11
  pip install "ldcon[web,instruments,analysis]"
@@ -15,6 +17,9 @@ Python 3.10+ on Linux. `experiment-core` installs automatically. Optional agent
15
17
  messaging: `pip install "ldcon[agents]"` (installs `fanharvard-agentbridge`).
16
18
  Provider CLIs and their authentication are separate.
17
19
 
20
+ Supported agent interfaces: **Claude Code, Codex and OpenCode**, with a DeepSeek
21
+ Harness adapter for card tasks.
22
+
18
23
  **Agents** monitor results, diagnose problems and run bounded characterization,
19
24
  parameter tuning and recovery through registered control cards. **Humans** choose
20
25
  the experiment, target, hardware configuration and physical safety limits, and
@@ -29,11 +34,14 @@ Missing data remains unknown; quality labels are distinct from physical safety.
29
34
 
30
35
  | Configuration | Hardware |
31
36
  | --- | --- |
32
- | ECDL / ESP32 | Wavemeter and data feed, ESP32 servo DAC/firmware, piezo driver, current/TEC controllers and supported AWGs (e.g. Siglent SDG) |
33
- | DFB/DBR | Wavemeter, current/TEC controller (e.g. Thorlabs CLD1015); ESP32 DAC and modulation input for native current PI |
37
+ | ECDL / digital servo | Wavemeter and data feed, compatible digital servo/DAC, piezo driver, current/TEC controllers and supported AWGs (e.g. Siglent SDG) |
38
+ | DFB/DBR | Wavemeter, current/TEC controller (e.g. Thorlabs CLD1015); compatible digital servo/DAC and modulation input for native current PI |
34
39
  | ECDL / DLCpro | TOPTICA DLCpro, wavemeter feedback; AWG/trigger connections for configured feedforward scans |
35
40
  | Spectral quality / studies | Fringe image source for secondary-peak analysis; scope/telemetry and AWG where required by the selected measurement |
36
41
 
42
+ For digital-servo hardware and integration details, please contact
43
+ [kenjishu@fas.harvard.edu](mailto:kenjishu@fas.harvard.edu).
44
+
37
45
  Tests use simulations, fake instruments and loopback services to cover control
38
46
  contracts, owner exclusivity, uncertain writes, cancellation/recovery, tuning,
39
47
  sweeps, configuration, quality reporting and Web behavior. They do not certify
@@ -43,3 +51,5 @@ a new physical setup. See [test suite](tests/).
43
51
  laser definitions, decks and assignments, with output disabled and placeholder
44
52
  connections. Installation starts no hardware or service and includes no credentials.
45
53
  [Publishing](docs/publishing.html) · [MIT license](LICENSE)
54
+
55
+ FanHarvard site configuration and deployment: [ldcon-fanharvard](https://github.com/FanHarvard/ldcon-fanharvard).
Binary file
@@ -0,0 +1,20 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 96 96" fill="none">
2
+ <title>LDCon: a laser diode with agent-guided feedback</title>
3
+ <rect width="96" height="96" rx="18" fill="#f8fafc"/>
4
+ <g stroke="#334155" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
5
+ <!-- Laser diode and its emitted beam. -->
6
+ <rect x="10" y="15" width="38" height="31" rx="6" fill="white"/>
7
+ <path d="M15 31h7m0-8v16l13-8-13-8m13 0v16m0-8h7"/>
8
+ <path d="M29 20l5-5m-1 0h1v1M38 22l5-5m-1 0h1v1" stroke="#dc2626" stroke-width="2"/>
9
+ <path d="M48 31h35m-7-7 7 7-7 7" stroke="#dc2626"/>
10
+ <!-- Feedback returns through the agent to the diode. -->
11
+ <path d="M78 43v20a8 8 0 0 1-8 8h-7M33 71H24a8 8 0 0 1-8-8v-9m-5 5 5-5 5 5"/>
12
+ <path d="M48 57v-5"/>
13
+ <circle cx="48" cy="50" r="2.5" fill="white"/>
14
+ <rect x="33" y="58" width="30" height="26" rx="6" fill="white"/>
15
+ <path d="M29 67v8m38-8v8" stroke-width="2.5"/>
16
+ <circle cx="42" cy="68" r="2" fill="#334155" stroke="none"/>
17
+ <circle cx="54" cy="68" r="2" fill="#334155" stroke="none"/>
18
+ <path d="M43 76h10" stroke-width="2.5"/>
19
+ </g>
20
+ </svg>
@@ -0,0 +1,62 @@
1
+ <!doctype html><html lang="en"><meta charset="utf-8">
2
+ <meta name="viewport" content="width=device-width,initial-scale=1"><title>Publishing ldcon</title>
3
+ <style>body{font:16px/1.7 system-ui;max-width:900px;margin:3rem auto;padding:0 1rem}pre{background:#f2f4f6;padding:1rem;overflow:auto}code{font-size:.9em}</style>
4
+ <h1>Publishing ldcon</h1><p>Public repository: <a href="https://github.com/FanHarvard/ldcon">FanHarvard/ldcon</a>.
5
+ Current version: 0.2.2. No production service is activated by publication.</p>
6
+ <h2>One-time PyPI setup</h2><p>A PyPI account owner creates a pending publisher at
7
+ <a href="https://pypi.org/manage/account/publishing/">PyPI publishing settings</a> with:</p>
8
+ <table><tr><th>Project name</th><td>ldcon</td></tr><tr><th>Owner</th><td>FanHarvard</td></tr>
9
+ <tr><th>Repository</th><td>ldcon</td></tr><tr><th>Workflow</th><td>release.yml</td></tr>
10
+ <tr><th>Environment</th><td>pypi</td></tr></table>
11
+ <p>Use the repository's <code>pypi</code> environment to restrict release access. Authentication uses
12
+ GitHub OIDC and PyPI Trusted Publishing; no long-lived PyPI API token belongs in this repository.
13
+ See the <a href="https://docs.pypi.org/trusted-publishers/creating-a-project-through-oidc/">official PyPI setup</a>.</p>
14
+ <h2>Updating an installation</h2>
15
+ <p>In the virtual environment used for the installation:</p>
16
+ <pre>python -m pip install --upgrade "ldcon[web,instruments,analysis,agents]"
17
+ python -m pip check</pre>
18
+ <p>This selects the latest LDCon release and its declared compatible dependencies. LDCon pins
19
+ experiment-core and fanharvard-agentbridge versions, so independent updates to those projects are
20
+ adopted when the LDCon dependency pins are updated. For standalone use, update either with
21
+ <code>python -m pip install --upgrade experiment-core</code> or
22
+ <code>python -m pip install --upgrade fanharvard-agentbridge</code>.</p>
23
+ <p>Updating a Python environment does not promote an immutable production release or restart a service.
24
+ The existing production installation uses its separate deployment and handover procedure.</p>
25
+ <h2>Updating GitHub</h2>
26
+ <p>Edit the public checkout, commit reviewed files and push to <code>main</code>. README and icon changes
27
+ are visible on GitHub after the push; they do not require a PyPI version bump. The icon source is
28
+ <code>docs/icon.svg</code>; regenerate its PNG with:</p>
29
+ <pre>rsvg-convert --width 512 --height 512 --output docs/icon.png docs/icon.svg</pre>
30
+ <p>The public checkout was split from the internal deployment repository. They do not synchronize
31
+ automatically. Port reviewed source changes and test fixtures explicitly; export deployment
32
+ configurations as disabled, sanitized examples. Preserve the public packaging metadata and exclude
33
+ credentials, inboxes and runtime state instead of copying the full deployment directory or its Git history.</p>
34
+ <h2>Publishing a new PyPI version</h2><p>Change <code>project.version</code> in <code>pyproject.toml</code>
35
+ to a new, unused version. Publish updated experiment-core or agentbridge dependencies first if needed.
36
+ When changing the experiment-core pin, update its checkout tag in both CI and release workflows too.</p>
37
+ <p>From a development environment with the build, test and role dependencies installed, build into an
38
+ empty directory so old distributions cannot be uploaded accidentally:</p>
39
+ <pre>release_dir=$(mktemp -d)
40
+ python -m build --outdir "$release_dir"
41
+ python -m twine check --strict "$release_dir"/*
42
+ python scripts/check_dist.py "$release_dir"
43
+ python scripts/check_secrets.py
44
+ python -m pip install --force-reinstall --no-deps "$release_dir"/*.whl
45
+ python -m pytest -q
46
+ python -m pip check</pre>
47
+ <p>Commit and push the reviewed changes. After CI succeeds, create a tag matching the new version
48
+ (<code>vX.Y.Z</code>) and publish a GitHub Release for it. That runs <code>release.yml</code>; alternatively
49
+ dispatch that workflow at the tag. The workflow checks the tag against package metadata, builds and audits distributions,
50
+ tests the wheel, and publishes through the dedicated environment. Do not reuse an uploaded PyPI version.
51
+ The CI workflow also checks Python 3.10, 3.12 and 3.13. An existing PyPI release's embedded README
52
+ changes only with a new package version; a GitHub push alone does not replace it.</p>
53
+ <h2>Site configuration</h2><p>FanHarvard deployment configuration and clone/install procedures live in
54
+ <a href="https://github.com/FanHarvard/ldcon-fanharvard">ldcon-fanharvard</a>.
55
+ That repository pins published packages; it does not vendor this library. Credential values and runtime state stay local.</p>
56
+ <h2>Public/private boundary</h2><p>Public: source, tests, documentation, MIT license and reviewed examples.
57
+ Private: credentials, .env/.pypirc files, runtime databases, job logs, agent conversations,
58
+ approval receipts, local deployment history and live service configuration. New public repositories
59
+ start from a reviewed snapshot; the internal Git history is not uploaded.</p>
60
+ <p>The secret scanner compares findings against individually reviewed non-secret fixtures and code
61
+ literals in <code>.secrets.baseline</code>. New findings fail CI. This complements artifact inspection;
62
+ it is not a proof that arbitrary future data is safe to publish.</p></html>
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ldcon"
7
- version = "0.2.0"
7
+ version = "0.2.2"
8
8
  description = "Laser operations, physical owners and fleet presentation"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -65,7 +65,17 @@ def snapshot(box):
65
65
  source = node.get('dither_source_unix_s', stamp) if key == 'dither_response' else stamp
66
66
  metrics[path] = dict(value=item, acquired_unix_s=source,
67
67
  valid=source is not None and node.get(key+'_valid', node.get('valid', True)) is not False)
68
- collect(value.get('content', value.get('data', value)))
68
+ document=value.get('content', value.get('data', value))
69
+ collect(document)
70
+ # DLC optics have their own HTTP acquisition clock. A new WSU UDP
71
+ # frequency sample must not refresh a cached/invalid fringe frame.
72
+ quality=(document.get('observation') or {}).get('quality') if isinstance(document,dict) else None
73
+ if isinstance(quality,dict):
74
+ for name in quality.get('metrics') or {}:
75
+ key='observation.quality.metrics.'+name
76
+ if key in metrics:
77
+ metrics[key]['valid']=quality.get('fresh') is True and quality.get('quality_valid') is True
78
+ metrics[key]['acquired_unix_s']=quality.get('acquired_unix_s')
69
79
  for source, target, scale, absolute in (
70
80
  ('error_hz','abs_error_hz',1.,True),
71
81
  ('native_interval_us','source_interval_s',1e-6,False),
@@ -74,6 +84,11 @@ def snapshot(box):
74
84
  raw=metrics[source]
75
85
  metrics[target]={**raw,'value':(abs(raw['value']) if absolute else raw['value'])*scale,
76
86
  'derived_from':source}
87
+ if 'integral_v' in metrics and 'control.integral_limit_v' in metrics:
88
+ integral,limit=metrics['integral_v'],metrics['control.integral_limit_v']
89
+ if limit['value']>0:
90
+ metrics['integral_utilization']={**integral,'value':abs(integral['value'])/limit['value'],
91
+ 'valid':integral['valid'] and limit['valid'],'derived_from':['integral_v','control.integral_limit_v']}
77
92
  return dict(jobs=jobs, metrics=metrics,
78
93
  authority='recorded data only; no physical state proof or new grant')
79
94
 
@@ -120,7 +135,7 @@ def run(directory, p, *, clock, sleep, cancel, emit, runtime=None, snapshot_fn=N
120
135
  if grant_dir.is_symlink():raise ValueError('Monitor grant directory must not be a symlink')
121
136
  grant_dir.mkdir(parents=True,exist_ok=True)
122
137
  atomic_json(grant_dir/(meta['id']+'.json'),dict(generation=state['generation'],bounds=p['background'],
123
- enabled=p['enabled'] and p['background']['enabled'] and not phase.startswith('stopped') and phase!='control_data_unavailable',
138
+ enabled=p['enabled'] and p['background']['enabled'] and not phase.startswith('stopped') and phase not in ('control_data_unavailable','waiting_controller'),
124
139
  last_seen=time.time(),max_age_s=max(30,p['sample_interval_s']*3),parameters_hash=digest(p)))
125
140
  except (ValueError,OSError):
126
141
  state['background_grant']='unavailable; passive review remains available'
@@ -203,6 +218,10 @@ def run(directory, p, *, clock, sleep, cancel, emit, runtime=None, snapshot_fn=N
203
218
  from ldcon.agents.agent_background import revoke_monitor
204
219
  revoke_monitor(box.root,laser_id,meta['id'],state['generation'])
205
220
  publish('disabled'); sleep(p['sample_interval_s']); continue
221
+ if p['background'].get('controller_operation')=='servo.dlcpro_frequency' and not any(
222
+ j.get('status')=='running' and any(c.get('operation',c.get('card'))=='servo.dlcpro_frequency'
223
+ for c in j.get('cards',[])) for j in last_snapshot.get('jobs',[])):
224
+ publish('waiting_controller'); sleep(p['sample_interval_s']); continue
206
225
  due = bool(p['interval_s'] and (state['last_review'] is None or now-state['last_review'] >= p['interval_s']))
207
226
  research = bool(p['history_task_card_id'] and p['history_interval_s'] and
208
227
  (state['last_history'] is None or now-state['last_history'] >= p['history_interval_s']) and
@@ -24,6 +24,7 @@ def parameters(card, overrides):
24
24
  execution_profile='', request_delegation=True,
25
25
  lookback_s=3600., sample_interval_s=1., timeout_s=1800., monitor_job_id='', evidence_images=[],
26
26
  adjustment_family='auto', adjustment_plan_card_id='agent-monitor', adjustment_objective='',
27
+ adjustment_measurement_cards={},
27
28
  adoption_mode='auto_within_approved')
28
29
  p = {**defaults, **card['parameters'], **overrides}
29
30
  if set(p) != set(defaults):
@@ -40,6 +41,10 @@ def parameters(card, overrides):
40
41
  raise ValueError('Invalid task prompt')
41
42
  # The native-only distribution need not install ECDL parameter adapters.
42
43
  if p['adjustment_family'] not in ('auto','current','pi','slow_loop','feedforward'):raise ValueError('Unknown adjustment family')
44
+ plans=p['adjustment_measurement_cards']
45
+ if not isinstance(plans,dict) or set(plans)-{'current','pi','slow_loop','feedforward'}:
46
+ raise ValueError('Invalid adjustment measurement cards')
47
+ for value in plans.values():identifier(value)
43
48
  if (not isinstance(p['adjustment_objective'],str) or '\x00' in p['adjustment_objective']
44
49
  or len(p['adjustment_objective'].encode())>4000):raise ValueError('Invalid adjustment objective')
45
50
  if card['operation']=='agent.history_review' and p['instruction_profile']!='research':
@@ -174,6 +179,8 @@ def run(directory, p, *, clock, sleep, cancel, emit, adapter_factory=None, bridg
174
179
  work_started=True
175
180
  if (invocation.get('adjustment_plan') or {}).get('kind') in ('dlc_pi_change_measure','dlc_pi_target_response'):
176
181
  from ldcon.agents.dlc_pi_adjustment import run as adjust
182
+ elif (invocation.get('adjustment_plan') or {}).get('kind') == 'dlc_adjustment':
183
+ from ldcon.agents.dlc_parameter_adjustment import run as adjust
177
184
  outcome=adjust(directory,p,clock=clock,sleep=sleep,cancel=cancel,emit=emit,
178
185
  selected=parent,decision_session=child)
179
186
  outcome['explanation']=child.explain(outcome)
@@ -0,0 +1,87 @@
1
+ """Protected monitor lifetime for attached DLC parameter comparisons.
2
+
3
+ This grants only explicitly configured, owner-supported adjustment families.
4
+ It cannot grant target excursions or changes to physical policy.
5
+ The worker binds the immutable monitor invocation; the owner checks its lifetime
6
+ again at each effect and can restore without waiting for the model.
7
+ """
8
+ from copy import deepcopy
9
+ import math
10
+ import os
11
+ from pathlib import Path
12
+ import time
13
+
14
+ from experiment_core.records import digest, safe_id
15
+ from ldcon.core.interface_schema import load_mapping
16
+ from ldcon.core.records import read_json
17
+
18
+
19
+ def validate_bounds(value):
20
+ fields = {'enabled', 'controller_operation', 'families', 'timeout_s'}
21
+ if (not isinstance(value, dict) or set(value) != fields
22
+ or type(value['enabled']) is not bool
23
+ or value['controller_operation'] != 'servo.dlcpro_frequency'
24
+ or not isinstance(value['families'],list) or not value['families']
25
+ or any(not isinstance(f,str) for f in value['families'])
26
+ or len(set(value['families']))!=len(value['families'])
27
+ or set(value['families'])-{'pi','current','slow_loop','feedforward'}
28
+ or type(value['timeout_s']) not in (int, float)
29
+ or not math.isfinite(value['timeout_s']) or not 1 <= value['timeout_s'] <= 86400):
30
+ raise ValueError('DLC monitor requires explicit adjustment families and a finite lifetime')
31
+ return deepcopy(value)
32
+
33
+
34
+ def check_grant(laser_id, binding, *, clock=time.time):
35
+ if not isinstance(binding, dict) or set(binding) != {'monitor_id', 'generation', 'parameters_hash'}:
36
+ raise ValueError('Invalid DLC monitor grant binding')
37
+ safe_id(laser_id); safe_id(binding['monitor_id'])
38
+ if any(not isinstance(binding[k], str) or not binding[k] for k in ('generation', 'parameters_hash')):
39
+ raise ValueError('Incomplete DLC monitor generation')
40
+ root = Path(os.environ.get('LDCON_ADAPTIVE_ROOT', ''))
41
+ if not root.is_absolute() or not root.is_dir() or root.resolve() != root:
42
+ raise ValueError('Protected monitor authority is unavailable')
43
+ path = root/laser_id/'monitors'/(binding['monitor_id']+'.json')
44
+ if any(p.is_symlink() for p in (path, path.parent, path.parent.parent)):
45
+ raise ValueError('Monitor authority must not follow symlinks')
46
+ grant = read_json(path, {})
47
+ if not isinstance(grant, dict):raise ValueError('Monitor authority is unavailable')
48
+ bounds = validate_bounds(grant.get('bounds'))
49
+ stamp, age = grant.get('last_seen'), grant.get('max_age_s')
50
+ if (grant.get('enabled') is not True or not bounds['enabled']
51
+ or any(grant.get(k) != binding[k] for k in ('generation', 'parameters_hash'))
52
+ or any(type(v) not in (int, float) or not math.isfinite(v) for v in (stamp, age))
53
+ or not 0 < age <= 180 or not 0 <= clock()-stamp <= age):
54
+ raise ValueError('Monitor grant stopped, changed or expired')
55
+ return grant
56
+
57
+
58
+ def bind(directory, p, laser):
59
+ """Bind a monitor task to its own frozen parent, never model-supplied text."""
60
+ if not p.get('monitor_job_id'):return None
61
+ from ldcon.agents.agent_monitor import parameters
62
+ from ldcon.agents.agent_background import control_root
63
+ directory = Path(directory)
64
+ monitor_id = safe_id(p['monitor_job_id'])
65
+ parent = directory.parent/monitor_id
66
+ if parent.is_symlink():raise ValueError('Monitor job must not be a symlink')
67
+ meta = read_json(parent/'job.json', {})
68
+ laser_id = laser['id']
69
+ source = load_mapping((parent/'laser.yaml').read_text())
70
+ invocation = read_json(parent/'invocation.json', {})
71
+ deck = load_mapping((parent/'interface-deck.yaml').read_text())
72
+ card = next((c for c in deck['cards'] if c['id'] == invocation.get('card_id')), None)
73
+ task = read_json(directory/'invocation.json', {})
74
+ if (meta.get('id') != monitor_id or source['id'] != laser_id
75
+ or not card or card['operation'] != 'agent.monitor'):
76
+ raise ValueError('Monitor belongs to another laser or operation')
77
+ plan = parameters(card, invocation['parameters'])
78
+ bounds = validate_bounds(plan['background'])
79
+ if (plan['task_card_id'] != task['card_id'] or not plan['enabled']
80
+ or not bounds['enabled'] or p['timeout_s'] > bounds['timeout_s']):
81
+ raise ValueError('Task differs from the monitor-approved adjustment plan')
82
+ root = control_root(directory.parent.parent)
83
+ grant = read_json(root/laser_id/'monitors'/(monitor_id+'.json'), {})
84
+ binding = dict(monitor_id=monitor_id, generation=grant.get('generation'), parameters_hash=digest(plan))
85
+ live = check_grant(laser_id, binding)
86
+ if live['bounds'] != bounds:raise ValueError('Monitor bounds differ from its frozen invocation')
87
+ return binding