PlateManager Services Architecture
The Problem: Parallel Service Paths Drifted
The previous PlateManager architecture split orchestration across independent
CompilationService and ZMQExecutionService modules. That split caused
state duplication and stale UI projections because compile and execute flows
could diverge in how they updated plate state, progress, and status strings.
Current Service Model
PlateManager now uses a unified service boundary:
BatchWorkflowServicefor compile + execute orchestrationExecutionServerStatusPresenterfor consistent status-line renderingprogress_batch_resetfor deterministic batch boundary resetsplate_config_resolverfor canonical per-plate pipeline config lookup
This service layer keeps the widget focused on UI state and delegates workflow policy to reusable service classes.
Canonical Workflow
Compile-only flow:
Build
CompileJobobjects from selected plates.Submit all compile jobs through the workflow service compile backend.
Wait all compile jobs.
Store compiled artifacts and mark orchestrator states.
Run flow:
Reset progress for a new batch.
Compile all selected plates first.
Submit all execution jobs with compile artifact IDs.
Poll completion per execution and converge states in one place.
Key Invariants
One service owns compile + run orchestration.
Batch reset always clears old progress before new work starts.
Plate list state is updated from a single source (workflow service callbacks).
Progress projection and server status text are derived data, not mutable cache.
Primary Modules
openhcs/pyqt_gui/widgets/shared/services/batch_workflow_service.pyopenhcs/pyqt_gui/widgets/shared/services/execution_server_status_presenter.pyopenhcs/pyqt_gui/widgets/shared/services/progress_batch_reset.pyopenhcs/pyqt_gui/widgets/shared/services/plate_config_resolver.py