flowchart TD
User["User clicks Run Validate Codelens"] --> Cmd["VS Code command turbine.runValidate"]
Cmd --> Disp["dispatchOnboardingAction kind=run_validate"]
Disp --> Cmds["vscode.commands.executeCommand"]
Disp --> Note["TurbineClient.actionInvoked"]
Cmds --> Req["LSP request turbine/validateSchema"]
Req --> VS["ValidateSchema.run_with_snapshot"]
VS --> Pub1["tour_service.publish_action_invoked run_validate"]
Note --> Handler["OnboardingActionInvoked handler"]
Handler --> Pub2["tour_service.publish_action_invoked run_validate"]
Pub1 --> Stream["ActionInvokedStream.publish"]
Pub2 --> Stream
Stream --> Watcher["ActionFired watcher subscribed for run_validate"]
Watcher --> Edge["false to true edge"]
Edge --> Bus["EventBus.publish StepCompleted"]
Bus --> Notify["server notify_step_completed"]
Notify --> Wire["turbine/onboarding/stepCompleted notification"]
Wire --> Engine["tour-engine receives stepCompleted"]
Engine --> Latch["unlockedSteps.add stepId"]
Latch --> Panel["post tour-step-unlocked to panel"]
Panel --> View["tour-view re-renders"]
View --> Enabled["Next button enabled"]
sequenceDiagram
actor User
participant Panel as Onboarding Panel webview
participant Engine as TourEngine extension
participant Disp as dispatchOnboardingAction
participant Client as TurbineClient
participant Service as tour_service
participant Stream as ActionInvokedStream
participant W as ActionFired watcher
participant Bus as EventBus
User->>Panel: open tour at run-validate step
Panel->>Engine: tour-next-step
Engine->>Client: watchStep tourId stepId
Client->>Service: watch_step
Service->>W: completion.watch ctx
W->>Stream: subscribe handler
W->>Service: returns Watcher
Note over Service: gated=true sent on stepDto
User->>Panel: clicks Run Validate Codelens chip
Panel->>Disp: kind=run_validate command args
Disp->>Client: actionInvoked tourId stepId run_validate
Disp->>Client: validateSchema uri
Client->>Service: actionInvoked routed to publish_action_invoked
Client->>Service: validateSchema also calls publish_action_invoked
Service->>Stream: publish run_validate
Stream->>W: handler kind=run_validate
W->>Bus: publish StepCompleted
Bus->>Service: notify_step_completed
Service->>Client: notification turbine/onboarding/stepCompleted
Client->>Engine: stepCompleted tourId stepId
Engine->>Engine: unlockedSteps.add stepId
Engine->>Panel: tour-step-unlocked
Panel->>User: Next button enabled
classDiagram
class StepCompletion {
<<Protocol>>
+watch(ctx) Watcher
}
class Watcher {
<<Protocol>>
+stop()
}
class WatchContext {
<<dataclass>>
+tour_id : str
+step_id : str
+yaml_parser : YamlParser
+diagnostics : DiagnosticSource
+introspection_source : IntrospectionSource
+scheduler : Scheduler
+event_bus : EventBus
+action_invoked_stream : ActionInvokedStream
+translate_uri : Callable
+buffers : Mapping
}
class FieldEquals {
<<dataclass>>
+file : str
+yaml_path : str
+expected : str
+watch(ctx) Watcher
}
class FieldPresent {
<<dataclass>>
+file : str
+yaml_path : str
+watch(ctx) Watcher
}
class DiagnosticCleared {
<<dataclass>>
+file : str
+code : str
+watch(ctx) Watcher
}
class IntrospectionPopulated {
<<dataclass>>
+watch(ctx) Watcher
}
class ActionFired {
<<dataclass>>
+kind : StepActionKind
+watch(ctx) Watcher
}
class Timer {
<<dataclass>>
+ms : int
+watch(ctx) Watcher
}
class StateBasedWatcher {
+stop()
}
class TimerWatcher {
+stop()
}
class ActionFiredWatcher {
+stop()
}
class Step {
<<dataclass>>
+id : str
+completion : StepCompletion
+action : StepAction
+skip : SkipAction
}
class TourService {
+watch_step(tour_id, step_id)
+unwatch_step()
+publish_action_invoked(kind)
}
StepCompletion <|.. FieldEquals
StepCompletion <|.. FieldPresent
StepCompletion <|.. DiagnosticCleared
StepCompletion <|.. IntrospectionPopulated
StepCompletion <|.. ActionFired
StepCompletion <|.. Timer
Watcher <|.. StateBasedWatcher
Watcher <|.. TimerWatcher
Watcher <|.. ActionFiredWatcher
FieldEquals ..> StateBasedWatcher : returns
FieldPresent ..> StateBasedWatcher : returns
DiagnosticCleared ..> StateBasedWatcher : returns
IntrospectionPopulated ..> StateBasedWatcher : returns
Timer ..> TimerWatcher : returns
ActionFired ..> ActionFiredWatcher : returns
Step --> StepCompletion : has-a
TourService --> Step : iterates
TourService --> WatchContext : builds
TourService --> Watcher : stores active