feat(replay-ui): show the step a violation was detected at

The witness evidence is the detecting step's state, so say which step that is
and let a reader jump to it.

Claude-Session: https://claude.ai/code/session_01Fj4wJUikdABuMQEETwW55J
This commit is contained in:
pj committed 2026-08-12 16:47:25 +05:30
1 parent eb492e53de
commit 32d0171b10
2 files changed
+25 -1

No files matched your search

+22 -1
View File
@@ -59,9 +59,30 @@ function WitnessView({
)}
</div>
) : null}
{witness.detected_step && witness.detected_step !== witness.step ? (
<div className="violations-panel-witness-line">
<span className="violations-panel-witness-key">detected at</span>
{onJumpToStep ? (
<button
type="button"
className="violations-panel-witness-step"
onClick={() => onJumpToStep(witness.detected_step as number)}
>
step {witness.detected_step}
</button>
) : (
<span className="violations-panel-witness-value">
step {witness.detected_step}
</span>
)}
</div>
) : null}
{evidence.length > 0 ? (
<details className="violations-panel-residual" open={open}>
<summary>witness</summary>
<summary>
witness
{witness.detected_step ? ` (state at step ${witness.detected_step})` : ""}
</summary>
<dl className="violations-panel-witness-evidence">
{evidence.map(([name, value]) => (
<div key={name} className="violations-panel-witness-line">
+3
View File
@@ -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<string, unknown>;
}