Skip to content

Scenario to Trace Data Flow

This diagram traces how a YAML scenario file flows through the FCC simulation engine, producing messages, workflow transitions, structured traces, and events on the bus. It spans scenarios/loader.py, simulation/engine.py, simulation/messages.py, simulation/traces.py, and messaging/bus.py. Every node transition emits an event, and every message is recorded into a MessageHistory ring so the run can be replayed. A simulation run terminates with a SimulationResult aggregating persona executions, validations, and traceability metadata.

The diagram below traces the scenario-to-trace pipeline.

flowchart LR
    subgraph Input
        S1[(Scenario YAML)]
        S2[ScenarioLoader.load]
    end
    subgraph Execute
        E1[SimulationEngine.run]
        E2{Next node?}
        E3[PersonaExecution]
        E4[Message payload]
    end
    subgraph Record
        R1[MessageHistory.record]
        R2[Trace append]
        R3[ValidationResult]
    end
    subgraph Publish
        P1[EventBus.publish]
        P2[(simulation.step events)]
        P3[(simulation.completed event)]
        P4[SimulationResult]
    end
    S1 --> S2 --> E1
    E1 --> E2
    E2 -- yes --> E3 --> E4 --> R1
    R1 --> R2
    E4 --> P1 --> P2
    E2 -- no --> R3 --> P1
    P1 --> P3 --> P4

Once SimulationEngine.run(start_node) begins, the scenario graph drives a loop: each iteration resolves the next workflow node, invokes the bound persona, captures the resulting Message, and appends to MessageHistory. The engine publishes simulation.step with the edge label so subscribers can build a live progress dashboard. On any ValidationResult with passed=False, a simulation.validation_failed event is published before the loop continues.

At termination the engine assembles a SimulationResult(scenario_id, status, personas_executed, artifacts, validations, traceability) and publishes simulation.completed. Subscriber failures push envelopes into the dead-letter queue so downstream consumers can reprocess without blocking the main loop. The same trace can be replayed offline via EventReplay against a serialized event log.

Data shapes

  • Stage 1 - Input: Scenario YAML on disk loaded by ScenarioLoader.load into a ScenarioSpec with setup.ai_config and workflow graph reference.
  • Stage 2 - Dispatch: SimulationEngine.run(start_node) walks the WorkflowGraph, materialising one PersonaExecution(persona, started_at, status, messages) per visited persona node.
  • Stage 3 - Message: Each node emits a Message(payload, origin, timestamp) consumed by the next node.
  • Stage 4 - Record: MessageHistory.record(node_id, msg, edge_label) captures the message plus the edge label for trace reconstruction.
  • Stage 5 - Validate: FCCValidator produces ValidationResult(rule, passed, severity, message, details) for schema and invariant checks.
  • Stage 6 - Publish: EventBus.publish(Event(event_type, source, payload, correlation_id, timestamp)) fires simulation.step during and simulation.completed at end of run.
  • Stage 7 - Aggregate: SimulationResult returned to the caller with full traceability dict for audit replay.

See also

  • Source: src/fcc/scenarios/loader.py, src/fcc/scenarios/models.py:26,56,67
  • Source: src/fcc/simulation/engine.py, src/fcc/simulation/messages.py, src/fcc/simulation/traces.py
  • Source: src/fcc/messaging/bus.py, src/fcc/messaging/events.py
  • Related class diagram: ../class-diagrams/simulation-engine.md
  • For audience tier: docs/for-beginners/quickstart-first-simulation.md