From 925b0617eff247db4afe097eef755fff9d81be62 Mon Sep 17 00:00:00 2001 From: PJ Date: Sat, 6 Jun 2026 12:46:41 +0530 Subject: [PATCH] test(trace): document ViolationsAreGreppable grep contract and lock-free WriteScreenshot --- internal/trace/writer.go | 3 +++ internal/trace/writer_test.go | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/internal/trace/writer.go b/internal/trace/writer.go index 7e29a53..970d8be 100644 --- a/internal/trace/writer.go +++ b/internal/trace/writer.go @@ -158,6 +158,9 @@ func (w *Writer) WriteStep(step Step) error { return w.encoder.Encode(step) } +// WriteScreenshot is lock-free: each call writes a distinct, uniquely-named +// file via os.WriteFile and touches no field of Writer, so concurrent calls +// never contend. func (w *Writer) WriteScreenshot(stepIndex int, png []byte) error { return w.writePNG(fmt.Sprintf("step-%05d.png", stepIndex), png) } diff --git a/internal/trace/writer_test.go b/internal/trace/writer_test.go index 2233b36..49ca2cf 100644 --- a/internal/trace/writer_test.go +++ b/internal/trace/writer_test.go @@ -330,6 +330,12 @@ func TestWriteStep_ConcurrentWritesAreWellFormed(t *testing.T) { } } +// Grep contract (intentional substring assertion, not a JSON round-trip): +// operators and CI scripts locate failing steps by grepping raw trace.jsonl for +// `"violations":[""]` without a JSON parser. Bug class: a serialization +// change (whitespace from indenting, renamed/reordered field, pointer slice) +// that keeps the Step parseable but breaks that exact on-disk byte shape would +// silently blind every grep-based tool. func TestWriteStep_ViolationsAreGreppable(t *testing.T) { directory := t.TempDir() writer, _ := NewWriter(directory)