Attribute violations to the causing step and render witness evidence (#59)

* feat(ltl): attribute violations to the obligation origin step

* feat(verifier): label evaluator observations with the runner step index

* feat(trace): carry the causing step in violation witnesses and summary

* feat(replay): move the violation marker to the causing step

* feat(replay-ui): render witness evidence in the violations panel

* feat(replay-ui): wire witnesses and step jump into violation panels

* fix(ltl): treat next obligations as vacuous at run end

* fix(runner): give the finalize trace record its own step index
This commit is contained in:
pj authored and GitHub committed 2026-06-05 23:46:36 +05:30
1 parent 19a470121f
commit 9958b0ddc8
15 files changed
+719 -85

No files matched your search

+5 -4
View File
@@ -91,7 +91,7 @@ func scanSteps(tracePath string) ([]StepSummary, []int64, int, time.Time, error)
reader := bufio.NewReaderSize(file, 64*1024)
steps := []StepSummary{}
offsets := []int64{}
violationCount := 0
attributions := []violationAttribution{}
var offset int64
for {
lineStart := offset
@@ -102,19 +102,20 @@ func scanSteps(tracePath string) ([]StepSummary, []int64, int, time.Time, error)
trimmed = trimmed[:len(trimmed)-1]
}
if len(trimmed) > 0 {
summary, partial, decodeErr := decodeStepSummary(trimmed)
summary, lineAttributions, decodeErr := decodeStepSummary(trimmed)
if decodeErr != nil {
return nil, nil, 0, time.Time{}, decodeErr
}
steps = append(steps, summary)
offsets = append(offsets, lineStart)
violationCount += partial
attributions = append(attributions, lineAttributions...)
}
if err != nil {
break
}
}
return steps, offsets, violationCount, info.ModTime(), nil
markViolations(steps, attributions)
return steps, offsets, len(attributions), info.ModTime(), nil
}
// Step decodes the full Step record at index n (1-based, matching trace.Step.Index).