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.
- {ldcon-0.2.0 → ldcon-0.2.2}/MANIFEST.in +1 -1
- {ldcon-0.2.0/src/ldcon.egg-info → ldcon-0.2.2}/PKG-INFO +14 -4
- {ldcon-0.2.0 → ldcon-0.2.2}/README.md +13 -3
- ldcon-0.2.2/docs/icon.png +0 -0
- ldcon-0.2.2/docs/icon.svg +20 -0
- ldcon-0.2.2/docs/publishing.html +62 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/pyproject.toml +1 -1
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_monitor.py +21 -2
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_task.py +7 -0
- ldcon-0.2.2/src/ldcon/agents/dlc_monitor_grant.py +87 -0
- ldcon-0.2.2/src/ldcon/agents/dlc_parameter_adjustment.py +274 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/dlc_pi_adjustment.py +7 -3
- ldcon-0.2.2/src/ldcon/agents/dlc_pi_plan.py +57 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/monitor_quality_binding.py +3 -2
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/operating_mode_client.py +5 -1
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/adjustment_plan.py +3 -0
- ldcon-0.2.2/src/ldcon/jobs/dlc_parameter_measurement.py +87 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/dlc_pi_measurement.py +69 -7
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/dlcpro_cards.py +18 -1
- ldcon-0.2.2/src/ldcon/owners/dlcpro_agent_setup.py +43 -0
- ldcon-0.2.2/src/ldcon/owners/dlcpro_client_liveness.py +48 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_deployment.py +3 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_ff_delta_adjustment.py +30 -15
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_observation.py +1 -0
- ldcon-0.2.2/src/ldcon/owners/dlcpro_operating_mode.py +45 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_owner.py +17 -5
- ldcon-0.2.2/src/ldcon/owners/dlcpro_parameter_trial.py +240 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_pi_protocol.py +22 -2
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_pi_trial.py +128 -9
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_service.py +4 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/web_runtime.py +3 -8
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/app.js +2 -1
- {ldcon-0.2.0 → ldcon-0.2.2/src/ldcon.egg-info}/PKG-INFO +14 -4
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon.egg-info/SOURCES.txt +16 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/golden-sr1092.json +7 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/golden-sr422.json +7 -0
- ldcon-0.2.2/tests/test_dlc_adjustment_web.cjs +25 -0
- ldcon-0.2.2/tests/test_dlc_monitor_admission.py +98 -0
- ldcon-0.2.2/tests/test_dlc_parameter_adjustment.py +310 -0
- ldcon-0.2.2/tests/test_dlcpro_agent_setup.py +49 -0
- ldcon-0.2.2/tests/test_dlcpro_client_liveness.py +118 -0
- ldcon-0.2.2/tests/test_dlcpro_operating_mode.py +235 -0
- ldcon-0.2.2/tests/test_dlcpro_parameter_trial.py +198 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_operating_mode_routes.py +7 -2
- ldcon-0.2.0/docs/publishing.html +0 -33
- ldcon-0.2.0/src/ldcon/agents/dlc_pi_plan.py +0 -24
- {ldcon-0.2.0 → ldcon-0.2.2}/.secrets.baseline +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/LICENSE +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/package-lock.json +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/package.json +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/scripts/check_dist.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/scripts/check_secrets.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/scripts/check_tag.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/scripts/install_wheel.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/setup.cfg +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/__init__.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/_moved.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agent_tools.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/__init__.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/adjustment_guidance.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/adjustment_quality.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_adapters.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_background.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_bundle.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_cards.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_config_access.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_configuration.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_configuration_policy.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_connect.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_device_parameters.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_execution.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_history.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_inbox_watch.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_interactive.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_interactive_hooks.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_language.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_log_context.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_log_read.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_log_watch.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_metrics.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_opencode_http.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_opencode_mcp.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_owner_status.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_profiles.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_providers.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_repairs.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_routing.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_runtime.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_sandbox.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_startup_notice.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_tools.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_window.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/agent_workspace.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/card_fallback.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/dlc_pi_response_plan.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/failure_policy.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/fallback_service.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/fallback_targets.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/gateway_role.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/manual_adjustment_grant.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/measurement_grant.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/notification_policy.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/report_pdf.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/resident_adjustment.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/resident_agent.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/resident_quality_apply.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/task_decisions.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/teams_card.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/agents/teams_destinations.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/cld_owner.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/cli.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/__init__.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/adjustment_registry.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/agent_authority.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/card_admission.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/card_definition.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/card_reporting.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/configuration.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/configuration_transaction.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/contracts.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/current_settings.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/deck_yaml.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/device_conditions.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/execution_context.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/instrument_client.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/interface_cards.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/interface_schema.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/laser_assets.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/metric_quantities.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/modulation.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/operation_registry.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/paths.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/period_context.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/records.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/result_reservations.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/site_bindings.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/state_layout.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/target_policy.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/telegraf.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/telemetry.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/core/temperature_settings.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/dashboard_metrics.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/device_registry.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/__init__.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/cld1015.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/cld1015_config.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/dlcpro.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/dlcpro_analog.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/dlcpro_console.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/dlcpro_priority.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/ecdl.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/esp32_servo.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/fizeau.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/frequency_sweep.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/influx_wavelength.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/metric_sources.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/native_dither_telemetry.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/rigol_scope.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/siglent.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/staircase.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/drivers/wsu_udp.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/esp32_time_telemetry.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/example_config.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/fallback_service.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/instrument_owner.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/instrument_service.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/interface_worker.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/job_service.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/__init__.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/adaptive_pid.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/adaptive_window_session.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/adjustment_continuation.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/axis_frequency.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/axis_frequency_report.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/background_parameter_session.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/background_pid_session.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/branch_maps.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/branch_target_migration.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/card_runtime.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/change_measure.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/change_measure_adapter.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/change_measure_dlc.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/change_measure_parameters.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/change_measure_target.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/current_cards.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/current_devices.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/dashboard_api.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/device_parameters.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/dlcpro_awg_analysis.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/dlcpro_awg_card.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_branch_hop.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_branch_recovery.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_devices.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_locked_sweep_proxy.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_mapped_recovery.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_mode_map.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_mode_recovery.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_online.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_operating_point.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_pi_commission.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_recovery.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_recovery_plan.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_recovery_test.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_relock.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_response_study.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_steady.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_thermal_context.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/ecdl_window_center.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/emission_card.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/fringe_sweep_reference.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/interface_devices.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/interface_worker.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/job_service.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/laser_live.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/learned_settling.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/lock_target.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/locked_triangle.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/measurement_acquisition.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/measurement_analysis.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/measurement_execution.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/measurement_notice.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/measurement_presets.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/measurement_report.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/measurement_statistics.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/metric_cards.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/metric_interface.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/modulation_sweep.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/native_background_session.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/native_current_acquire.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/native_current_card.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/native_current_online.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/native_ff_proxy.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/native_ff_sweep.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/online_pid.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/operating_point.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/operating_point_proxy.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/operation_execution.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/operation_history.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/optical_broker.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/pi_algorithms.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/pi_response.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/progress.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/quality_baseline.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/recovery_decisions.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/recovery_history.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/recovery_procedure.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/recovery_reference.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/recovery_stationary.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/response_algorithms.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/response_comparison.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/response_record.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/runtime_parameters.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/settling_profile.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/shot_analysis.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/simulation.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/slow_control.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/slow_current.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/study_adoption.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/study_execution.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/sweep_ff_analysis.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/sweep_ff_optimization.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/sweep_ff_plan.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/sweep_ff_report.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/sweep_ff_transport.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/sweep_tracking.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/sweep_verdict.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/target_response.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/target_response_analysis.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/target_response_control.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/target_response_decisions.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/target_response_experiment.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/target_response_feedforward.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/target_response_search.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/target_response_shift.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/target_response_thermal.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/target_response_thermal_experiment.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/target_sequence.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/temperature_identification.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/wavelength_history.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/window_actions.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/window_center.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/window_control.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/window_decisions.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/window_sampling.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/jobs/workflow_artifacts.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/migration/__init__.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/migration/migration_decks.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/migration/migration_readiness.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/migration/migration_relocation.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/monitor_owner.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owner_telemetry.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/__init__.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/adc_log_threshold.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/background_grants.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/cld_instrument_owner.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/cld_owner.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/cld_projection.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/cld_system_owner.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/current_owner.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/device_registry.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_awg_plan.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_awg_port.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_awg_protocol.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_awg_return.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_awg_sweep.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_awg_timing.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_awg_tracking.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_awg_tracking_guard.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_awg_tracking_report.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_awg_zero.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_ff.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_ff_adjustment.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_frequency_window.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_readback.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_target_changes.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_target_step.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_target_store.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/dlcpro_telemetry.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_background_parameters.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_background_pid.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_hot_control.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_independent_pid.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_locked_study.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_locked_sweep.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_native_pid.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_optical.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_owner.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_policy_reload.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_prelock.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_projection.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_steady_owner.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_steady_policy.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_target_ff.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_target_settling.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_tec_pair.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/ecdl_thermal_study.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/emission.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/emission_adapters.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/esp32_native_client.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/esp32_native_owner.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/esp32_time_telemetry.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/esp32_udp_gate.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/external_sweep_guard.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/flexible_native_trial.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/fringe_peaks.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/full_data_log.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/instrument_identity.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/instrument_owner.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/instrument_projection.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/instrument_service.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/migration_physical_lock.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/monitor_owner.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/native_assembly.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/native_assembly_host.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/native_background.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/native_current_tuning.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/native_ff_proof.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/native_instrument_owner.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/native_modulation_limits.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/native_policy_reload.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/native_policy_safety.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/native_policy_update.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/native_system_owner.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/operating_mode_owner.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/owner_projection.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/owner_telemetry.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/pi_handover.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/projection_transport.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/remote_instruments.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/sdg_client.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/sdg_owner.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/tec_rate.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/owners/wsu_udp_monitor.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/report_pdf.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/agent-model-options.json +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/agent_contract/adjustment.txt +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/agent_contract/common.txt +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/agent_contract/diagnosis.txt +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/agent_contract/research.txt +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/agent_contract/response_optimization.txt +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/examples/README.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/examples/assignments/sr1092.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/examples/assignments/sr422.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/examples/assignments/thf685.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/examples/interface-decks/dfb-dbr-ldc-tec.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/examples/interface-decks/ecdl-dlcpro.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/examples/interface-decks/ecdl-pzt-ldc-tec.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/examples/lasers/sr1092.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/examples/lasers/sr422.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/examples/lasers/thf685.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/report_template/ldconreport.cls +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/resources/report_template/report.tex +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/__init__.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/agent_approval_api.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/agent_settings_api.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/agent_task_api.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/control_readback.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/dashboard_activity.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/dashboard_controls_revision.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/dashboard_metrics.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/dashboard_snapshot.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/dashboard_state.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/dashboard_wavelength.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/device_parameters_api.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/dither_quality.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/dlcpro_target_api.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/dlcpro_target_query.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/failure_api.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/gateway_lan.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/grafana_activity.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/grafana_dashboard.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/grafana_dlcpro.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/grafana_quality.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/interface_projection.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/job_registry.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/job_report.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/laser_operations.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/lock_target_api.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/lock_target_queue.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/log_archive.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/metric_query_profiles.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/online_position.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/operating_mode_api.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/operation_api.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/operation_observation.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/operations_settings.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/quality_threshold_metrics.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/shot_analysis_api.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/sweep_api.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/sweep_guard.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/target_reference_panel.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/teams_destinations_api.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/web_fleet.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/web_server.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web/window_api.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/agent-settings.css +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/agent-settings.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/agent-settings.js +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/app.css +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/card-browser.js +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/card-guide.js +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/acquire.metrics.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/agent.history_review.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/agent.log_watch.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/agent.monitor.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/agent.request.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/agent.resident.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/agent.task.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/commission.ecdl_pi.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/identify.axis_frequency.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/identify.current_response.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/laser.emission.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/measure.batch.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/measure.change.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/measure.target_response.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/monitor.wavelength.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/notify.teams.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/optimize.settling_criteria.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/optimize.target_feedforward.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/optimize.target_step.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/optimize.target_thermal.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/plan.ecdl_recovery.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/prepare.ecdl_recovery.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/recover.ecdl_mode_hop.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/report.grafana_dashboard.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/servo.current_pid.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/servo.dlcpro_frequency.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/servo.ecdl_steady_lock.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/servo.native_current.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/study.ecdl_current_response.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/study.ecdl_locked_current_map.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/study.ecdl_mode_map.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/study.ecdl_thermal_context.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/study.target_response.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/sweep.current_modulation.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/sweep.dlcpro_frequency.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/sweep.servo_modulation.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/test.ecdl_recovery.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/tune.ecdl_initial_point.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/tune.ecdl_operating_point.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/tune.ecdl_window_center.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/tune.native_current.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/tune.pid_coordinate_search.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/tune.pid_factor_reduction.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/tune.pid_online.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/cards/tune.temperature_once.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/committing-input.js +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/configuration-editor.js +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/dashboard-state.js +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/failures.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/failures.js +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/fallback.css +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/fallback.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/fallback.js +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/fleet-settings.js +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/fleet.css +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/fleet.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/fleet.js +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/gateway-presentation.js +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/grafana-help.js +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/help.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/i18n.js +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/index.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/laser-workspace.js +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/modulation.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/modulation.js +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/reservations.html +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/reservations.js +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/teams-settings.js +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/window-actions.js +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_assets/workspace.css +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_fleet.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon/web_server.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon.egg-info/dependency_links.txt +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon.egg-info/entry_points.txt +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon.egg-info/requires.txt +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/src/ldcon.egg-info/top_level.txt +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/__init__.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/conftest.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/dashboard_fixture.cjs +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/dlcpro-fw19.json +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/var/device-owners/cld1015-M01343851/config.json +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/var/device-owners/esp32servocon-sr1092/config.json +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/var/device-owners/scope-sr422-sr1092/config.json +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/var/device-owners/sr422/config.json +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/var/instrument-owners/bk4054b-51524H117/config.json +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/var/instrument-owners/sdg2042x-SDG2XFBCA00839/config.json +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/var/instrument-owners/sdg2042x-SDG2XFBCA00845/config.json +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/var/lasers/sr1092/config/assignments/sr1092.yaml +0 -0
- {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
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/var/lasers/sr1092/config/lasers/sr1092.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/var/lasers/sr1092/laser-layout.json +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/var/lasers/sr422/config/assignments/sr422.yaml +0 -0
- {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
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/var/lasers/sr422/config/lasers/sr422.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/effective-settings/var/lasers/sr422/laser-layout.json +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/entry-startup/assembly-definition.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/entry-startup/sr1092-broker.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/fixtures/pi-handover-v1.json +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/legacy_mapped_recovery_fixture.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/legacy_rearm_trim_fixture.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/legacy_recovery_executor_fixture.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/legacy_recovery_plan_fixture.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/legacy_recovery_test_fixture.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/measurement_fixtures.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/recovery_legacy_fixtures.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/examples/dlcpro/assignment.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/examples/dlcpro/deck.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/examples/dlcpro/existing-ecdl-calibration.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/examples/dlcpro/laser.offline.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/examples/dlcpro/owner.offline.json +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/examples/dlcpro/pi-agent-cards.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/examples/dlcpro/thf685/laser.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/examples/dlcpro/thf685/owner.json +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/examples/measurement-decks/dfb-dbr-ldc-tec.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/examples/measurement-decks/ecdl-pzt-ldc-tec.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/examples/interface-config/assignments/sr1092.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/examples/interface-config/assignments/sr422.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/examples/interface-config/interface-decks/dfb-dbr-ldc-tec.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/examples/interface-config/interface-decks/ecdl-pzt-ldc-tec.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/examples/interface-config/lasers/sr1092.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/examples/interface-config/lasers/sr422.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/tests/fixtures/live-20261022/assignments/sr1092.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/tests/fixtures/live-20261022/assignments/sr422.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/tests/fixtures/live-20261022/interface-decks/dfb-dbr-ldc-tec.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/tests/fixtures/live-20261022/interface-decks/ecdl-pzt-ldc-tec.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/tests/fixtures/live-20261022/lasers/sr1092.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/tests/fixtures/live-20261022/lasers/sr422.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/tests/test_esp32_native_current.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/tests/test_lock_target.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/tests/test_native_ff_owner.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/jobs/tests/test_native_live_moves.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/ops/effective_settings.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/ops/inspect_dlcpro.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/ops/prepare_pi_handover.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/ops/trim_owner_config.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/ops/update_pi_handover.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/owner/tests/fake_projection.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/owner/tests/fake_rig.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/owner/tests/locked_sweep_settings.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/owner/tests/test_background_pid_owner.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/owner/tests/test_locked_sweep_owner.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/scripts/monitor_configuration.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/scripts/test_live_background_handoff.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/tests/test_ecdl_acquisition_gate_fixes.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/tests/test_learned_settling.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/web/examples/interface-config/assignments/sr1092.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/web/examples/interface-config/assignments/sr422.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/web/examples/interface-config/interface-decks/dfb-dbr-ldc-tec.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/web/examples/interface-config/interface-decks/ecdl-pzt-ldc-tec.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/web/examples/interface-config/lasers/sr1092.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/web/examples/interface-config/lasers/sr422.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/web/tests/fixtures/live-20261022/assignments/sr1092.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/web/tests/fixtures/live-20261022/assignments/sr422.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/web/tests/fixtures/live-20261022/interface-decks/dfb-dbr-ldc-tec.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/web/tests/fixtures/live-20261022/interface-decks/ecdl-pzt-ldc-tec.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/web/tests/fixtures/live-20261022/lasers/sr1092.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/support/web/tests/fixtures/live-20261022/lasers/sr422.yaml +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_adaptive_window_session.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_adjustment_continuation.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_adjustment_guidance.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_adjustment_guidance_web.cjs +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_adjustment_quality.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_adopt_after_prewrite_reject_20261028.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_agent_background_gateway.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_agent_difficulty_routing.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_agent_host_integration.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_agent_model_negotiation.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_agent_monitor_history.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_agent_providers.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_agent_routing_layout.cjs +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_agent_settings_api.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_agent_settings_ui.cjs +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_agent_task_tool_arguments.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_agent_tasks.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_approval_layout_owner.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_background_foreground_native_matrix.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_background_start_observation.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_background_window_session.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_card_browser_assets.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_card_browser_ui.cjs +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_card_readiness.cjs +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_card_start_reasons.cjs +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_change_measure.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_change_measure_adapter.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_change_measure_dlc.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_change_measure_target.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_claude_interactive_metadata.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_claude_profile_transport.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_cld_system_boundary.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_committing_input.cjs +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_config_two_layer_step34.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_configuration_numeric_roundtrip.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_configuration_review_refresh.cjs +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_controller_status_projection.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dashboard_activity.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dashboard_polish.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dashboard_workspace.cjs +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_decision_progress_prefix.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_display_state_consistency.cjs +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dither_pause_20261027.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dither_quality_review_20261028.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dither_review_aggregation_20261028.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlc_pi_adjustment.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlc_pi_target_steps.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlc_response_policy.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlc_trace_state.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_adc_authority.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_awg.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_awg_async.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_awg_card.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_awg_enable.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_awg_identity.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_awg_protocol.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_awg_return.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_awg_tracking.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_awg_tracking_failures.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_awg_tracking_guard.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_awg_zero.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_console.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_fast_servo.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_ff_adjustment.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_ff_delta_adjustment.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_frequency_window.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_grafana.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_lock_input_window.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_native_scan_frequency.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_offline.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_pi_trial.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_target_api.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_target_api_fleet.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_target_api_routing.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_telemetry.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_tracking_io_budget.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_tracking_timing_io.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_dlcpro_udp.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_ecdl_branch_hop.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_ecdl_independent_pid.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_ecdl_ldc_target_ff.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_ecdl_owner_readopt.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_ecdl_owner_startup_adoption.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_ecdl_ready_target.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_ecdl_rearm_trim.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_ecdl_recovery_card.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_ecdl_settings_adopt.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_ecdl_target_settling.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_ecdl_tec_alignment_approach.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_effective_settings.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_emission.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_emission_native.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_entry_startup.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_failure_review.cjs +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_fleet_pdf_reports.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_gateway_defaults_ui.cjs +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_gateway_lan.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_gateway_notifications.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_gateway_presentation.cjs +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_gateway_presentation.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_http_request_ids.cjs +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_job_report.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_legacy_broker_projection.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_live_control_bulk.cjs +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_lock_target_correlation.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_measurement_acquisition.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_measurement_execution_integration.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_measurement_parameter_transactions.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_measurement_plan_authority.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_measurement_presets.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_midpoint_pilot.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_monitor_readback.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_moved_modules.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_native_assembly_adoption.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_native_background.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_native_integral_hotload.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_native_modulation_limits.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_native_owner_readopt.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_native_post_retarget_recentre.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_native_system_boundary.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_native_target_policy_update.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_notification_policy.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_opencode_mcp_lifetime.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_opencode_notification_queue.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_opencode_shared.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_operating_guidance_fleet.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_operating_mode_owner.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_operating_point_latency.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_operating_point_readback_failure.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_operation_execution.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_operation_gateway.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_operation_history.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_operation_observation.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_operation_record_delivery.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_owner_projection.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_package_boundary.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_parameter_workspace.cjs +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_pi_algorithm_identity.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_pi_public_retirement.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_pi_release_update.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_pi_response_workflow.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_pi_trial_envelope_20261028.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_preflight_reference_resolution.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_projection_transport.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_public_examples.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_quality_baseline.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_quality_baseline_hooks.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_quality_report_only.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_quality_threshold_layout.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_recovery_decisions.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_recovery_explicit_policy.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_recovery_history.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_recovery_reference_v2.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_recovery_without_map_lookup.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_refresh_layout.cjs +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_report_policy.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_resident_adjustment.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_resident_adjustment_web.cjs +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_resident_quality_apply.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_response_algorithm_integration.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_response_comparison.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_rollout_site_boundaries.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_settling_profile_consumer.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_single_laser_layout.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_stationary_unlimited_recovery.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_steady_planner_hold_only.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_steady_recovery_retirement.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_study_adoption.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_study_execution.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_study_history_display.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_sweep_admission.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_sweep_ff_analysis.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_sweep_ff_optimization.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_sweep_ff_report.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_sweep_ff_transport.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_target_cancel_ui.cjs +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_target_feedforward.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_target_ff_completion.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_target_response.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_target_response_control.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_target_response_experiment.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_target_response_feedforward.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_target_response_search.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_target_response_shift.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_target_response_web.cjs +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_target_sequence.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_target_step_authority.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_target_text_formats.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_task_decisions.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_task_profile_ui.cjs +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_teams_destinations.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_teams_settings_ui.cjs +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_unified_quality.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_window_hop_boundary_20261027.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_window_observable_selection.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_workspace_inventory.py +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_workspace_selector.cjs +0 -0
- {ldcon-0.2.0 → ldcon-0.2.2}/tests/test_wsu_udp_monitor.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ldcon
|
|
3
|
-
Version: 0.2.
|
|
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**,
|
|
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 /
|
|
73
|
-
| DFB/DBR | Wavemeter, current/TEC controller (e.g. Thorlabs CLD1015);
|
|
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**,
|
|
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 /
|
|
33
|
-
| DFB/DBR | Wavemeter, current/TEC controller (e.g. Thorlabs CLD1015);
|
|
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>
|
|
@@ -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
|
-
|
|
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
|
|
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
|