diff --git a/replay-ui/src/panels/ViolationsPanel.tsx b/replay-ui/src/panels/ViolationsPanel.tsx index 1c6a73e..85bc5bb 100644 --- a/replay-ui/src/panels/ViolationsPanel.tsx +++ b/replay-ui/src/panels/ViolationsPanel.tsx @@ -59,9 +59,30 @@ function WitnessView({ )} ) : null} + {witness.detected_step && witness.detected_step !== witness.step ? ( +
+ detected at + {onJumpToStep ? ( + + ) : ( + + step {witness.detected_step} + + )} +
+ ) : null} {evidence.length > 0 ? (
- witness + + witness + {witness.detected_step ? ` (state at step ${witness.detected_step})` : ""} +
{evidence.map(([name, value]) => (
diff --git a/replay-ui/src/types.ts b/replay-ui/src/types.ts index dfa8708..601187b 100644 --- a/replay-ui/src/types.ts +++ b/replay-ui/src/types.ts @@ -128,6 +128,9 @@ export interface Witness { // which for deferred obligations (next, eventually) is earlier than the // step whose record carries the witness. step?: number; + // detected_step is the step whose evaluation produced the violation. The + // extractors below are that step's state, not step's. + detected_step?: number; extractors?: Record; }