04. Workflow and State Model
Why This Page Matters
If a newcomer understands only one architectural idea in this repo, it should probably be this one:
the workstation behaves through explicit state, not through scattered boolean flags and UI event shortcuts.
That choice drives command availability, machine readiness, run transitions, fault handling, and recovery semantics.
The Central State Model
The most important state type in the repo is:
src/InspectionPrototype.Application/State/AppState.cs
AppState is the canonical runtime snapshot. It includes:
- connection state
- workflow state
- motion state
- camera state
- safety signals
- stage position
- loaded recipe and recipe catalog
- active run and last run summary
- run history
- active alarms and diagnostics
- latest telemetry and frame
- pipeline counters and operational counters
- simulator profile catalog and selected profile
This is the concrete implementation of ADR-001.
Why A Canonical State Store Was Chosen
Without one central state model, this app would be unusually easy to break:
- background services would update UI state directly
- command guards would drift apart
- machine readiness would become inconsistent
- tests would need to boot more of the UI stack to verify behavior
The central store is not there for style points. It is there because the app has several independent producers:
- workflow orchestration
- motion updates
- safety signal changes
- telemetry streaming
- frame streaming
- fault injection and clearance
- startup hydration for history and recipes
Workflow State
The most visible state machine is WorkflowState:
IdlePreparingHomingReadyRunningStoppingStoppedCompletedAbortedFaulted
Relevant file:
src/InspectionPrototype.Application/State/WorkflowState.cs
The happy-path story is simple:
Idle or Ready -> Preparing -> Running -> Completed
But the real teaching value comes from the non-happy paths:
Homingis explicitStoppingis explicitAbortedis distinct fromStoppedFaultedis distinct from both operator stop and operator abort
Quick Workflow Sketch
Idle/Ready
|
v
Preparing --> Running --> Completed
|
+--> Stopping --> Stopped
|
+--> Aborted
|
+--> Faulted --(clear + recover)--> Idle/Ready
Homing --> Idle/ReadyThis sketch is intentionally simplified, but it captures the teaching point: the repo models graceful stop, immediate abort, and unsafe fault as different runtime stories.
Command Guards
Command enablement is intentionally derived from state rather than hand-maintained in the UI.
Relevant file:
src/InspectionPrototype.Application/Guards/CommandGuards.cs
This means commands such as:
ConnectHomeStartStopAbortAcknowledgeRecover
all use the same underlying runtime truth.
That is a strong teaching example because it prevents a common WPF mistake: putting business rules inside button-enable logic spread across view models and XAML.
Workflow Ownership
WorkflowService owns state transitions and runtime coordination.
Relevant file:
src/InspectionPrototype.Application/Services/WorkflowService.cs
This service coordinates:
- connection lifecycle
- homing
- run startup
- stop and abort behavior
- terminal run summaries
- fault handling
- recovery
- history updates
- recipe catalog loading into active state
This is one of the most important design decisions in the repo. The app prefers explicit orchestration over “smart” UI code.
Trade-Offs
Benefits
- state transitions are inspectable
- command semantics stay consistent
- tests can verify runtime behavior without the full UI
- the architecture matches the mental model of a machine workstation
Costs
AppStatebecomes broadWorkflowServicebecomes a high-context file- newcomers must learn several related state types together
These costs are real. But they are easier to manage than hidden state duplication.
Practical Reading Path
To understand the runtime model well:
- read
AppState.cs - read
WorkflowState.cs - read
CommandGuards.cs - read
WorkflowService.cs - run the happy-path and stop/abort/fault scenarios while those files are open
That combination makes the architecture much easier to internalize.
Related Lessons
- 08. State Management in .NET - Real World
- 08. State Machines in .NET
- 20. Advanced Async Coordination
- 05. Machine States Lifecycle Overview
Diagram Brief
Title: Workflow and canonical state modelPurpose: Show the main workflow states and how command guards depend on a wider canonical state snapshotAudience: newcomer developer learning why the repo uses explicit stateNodes: AppState, ConnectionState, WorkflowState, MotionState, SafetySignals, LoadedRecipe, ActiveRunState, ActiveAlarms, CommandGuardsEdges: AppState aggregates the other state partitions; CommandGuards evaluate AppState; WorkflowService mutates AppState; WorkflowState transitions between Idle, Homing, Preparing, Running, Stopping, terminal states, and FaultedGrouping: Canonical state object, sub-state partitions, guard evaluation, workflow transitionsCaption: The workflow state machine is only one part of the model; command correctness depends on the full canonical app stateDestination file path:docs/diagrams/source/architecture-04-workflow-state-model.drawio