Skip to content

02. Central App State and Workflow Ownership

The Core Runtime Decision

The most important runtime decision in the repo is documented in ADR-001: Use Central App State Store:

  • there is one canonical AppState
  • the application layer owns state transitions
  • view models project state rather than owning parallel truth
  • command guards derive from canonical state

This choice appears in:

  • src/InspectionPrototype.Application/State/AppState.cs
  • src/InspectionPrototype.Application/Services/AppStateStore.cs
  • src/InspectionPrototype.Application/Guards/CommandGuards.cs
  • src/InspectionPrototype.Application/Services/WorkflowService.cs

Why One Canonical AppState

AppState is intentionally broad. It contains:

  • connection, workflow, motion, and camera state
  • safety signals
  • stage position
  • loaded recipe and recipe catalog
  • active run, last run summary, and run history
  • active alarms and diagnostics
  • latest telemetry and latest frame
  • pipeline counters and operational counters
  • simulator profile catalog and selected profile

That breadth can look heavy at first, but it solves a real problem: the runtime has many background producers, and the UI still needs one coherent truth.

Without a canonical state model, this app would be unusually easy to break:

  • command rules would drift
  • machine readiness would be inconsistent
  • view models would start caching their own flags
  • tests would need more UI bootstrapping to verify behavior

Why AppStateStore Is So Small

The mutation owner is:

  • src/InspectionPrototype.Application/Services/AppStateStore.cs

It is deliberately simple:

  • one current snapshot
  • one lock
  • one Update method
  • one StateChanged event

That simplicity is a feature. The repo does not need a full event-sourcing or reducer framework to teach good state ownership. It just needs one place where everyone knows runtime mutation goes.

Command Guards Depend On Shared Truth

Command semantics live in:

  • src/InspectionPrototype.Application/Guards/CommandGuards.cs

Examples:

  • CanStart depends on connection, recipe, homing, safety, no critical fault, and workflow state
  • CanStop depends on active workflow state
  • CanAbort is valid in a broader set of transitional states
  • CanRecover depends on both Faulted state and fault clearance

This is a great teaching example because it shows how command legality should come from runtime truth, not from scattered button logic.

Why WorkflowService Owns Orchestration

WorkflowService is the runtime coordinator.

It owns:

  • connection lifecycle
  • homing
  • recipe promotion into active runtime state
  • run startup
  • stop and abort
  • fault handling and recovery
  • terminal summary creation
  • history updates

This makes it a high-context service, but that is preferable to spreading workflow rules across view models, code-behind, and simulator classes.

Trade-Offs

Benefits

  • one shared runtime vocabulary
  • clearer testing seams
  • predictable command behavior
  • thinner presentation layer

Costs

  • AppState becomes large
  • WorkflowService demands more careful reading
  • changes to runtime semantics often touch several state-related files together

This is still a good fit for the repo. The app is intentionally stateful, so its architecture should make state explicit.

Diagram Brief

  • Title: Canonical state and workflow ownership
  • Purpose: Show how AppState, AppStateStore, CommandGuards, and WorkflowService cooperate
  • Audience: newcomer developer learning ownership boundaries
  • Nodes: AppState, AppStateStore, WorkflowService, CommandGuards, MainViewModel, Background Services
  • Edges: background services and workflow service update AppState through AppStateStore; command guards evaluate AppState; MainViewModel projects AppState
  • Grouping: State storage, orchestration, guard evaluation, projection
  • Caption: Runtime correctness comes from one shared state model and one clear mutation path
  • Destination file path: docs/diagrams/source/course-04-02-central-app-state-and-workflow-ownership.drawio

Docs-first project memory for AI-assisted implementation.