From 4ee3d97cfff287acc9a55dcda60a2b64afc34246 Mon Sep 17 00:00:00 2001 From: PJ Date: Sun, 31 May 2026 15:39:32 +0530 Subject: [PATCH] refactor(trace): rename Step.Action to Step.NextAction The trace step's action field is the action chosen FOR THE NEXT iteration based on observing this step's hierarchy, not the action that produced this step. Rename Step.Action to Step.NextAction and the JSON tag to next_action to make causality explicit at the data level. --- internal/trace/writer.go | 3 ++- internal/trace/writer_test.go | 18 +++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/internal/trace/writer.go b/internal/trace/writer.go index 9578da1..da7e28d 100644 --- a/internal/trace/writer.go +++ b/internal/trace/writer.go @@ -17,7 +17,8 @@ type Step struct { Timestamp time.Time `json:"timestamp"` Screen string `json:"screen,omitempty"` Snapshots map[string]json.RawMessage `json:"snapshots,omitempty"` - Action *Action `json:"action,omitempty"` + // NextAction is the action chosen for the next iteration based on observing this step. + NextAction *Action `json:"next_action,omitempty"` Exceptions []Exception `json:"exceptions,omitempty"` Violations []string `json:"violations,omitempty"` Hierarchy *hierarchy.Tree `json:"hierarchy,omitempty"` diff --git a/internal/trace/writer_test.go b/internal/trace/writer_test.go index 454656c..24b846d 100644 --- a/internal/trace/writer_test.go +++ b/internal/trace/writer_test.go @@ -102,7 +102,7 @@ func TestWriteStep_HierarchyAndResidualsRoundTrip(t *testing.T) { step := Step{ Index: 1, Timestamp: time.Now().UTC(), - Action: &Action{ + NextAction: &Action{ Kind: "tap", Selector: "id:next", ResolvedBounds: &BoundsRecord{X: 10, Y: 20, Width: 100, Height: 50}, @@ -120,14 +120,14 @@ func TestWriteStep_HierarchyAndResidualsRoundTrip(t *testing.T) { if err := json.Unmarshal(body, &got); err != nil { t.Fatalf("bad jsonl: %v\n%s", err, body) } - if got.Action.Selector != "id:next" { - t.Errorf("selector = %q", got.Action.Selector) + if got.NextAction.Selector != "id:next" { + t.Errorf("selector = %q", got.NextAction.Selector) } - if got.Action.ResolvedBounds == nil || got.Action.ResolvedBounds.Width != 100 { - t.Errorf("resolved_bounds round-trip wrong: %+v", got.Action.ResolvedBounds) + if got.NextAction.ResolvedBounds == nil || got.NextAction.ResolvedBounds.Width != 100 { + t.Errorf("resolved_bounds round-trip wrong: %+v", got.NextAction.ResolvedBounds) } - if got.Action.TapPoint == nil || got.Action.TapPoint.X != 60 { - t.Errorf("tap_point round-trip wrong: %+v", got.Action.TapPoint) + if got.NextAction.TapPoint == nil || got.NextAction.TapPoint.X != 60 { + t.Errorf("tap_point round-trip wrong: %+v", got.NextAction.TapPoint) } if string(got.Residuals["prop1"]) != `{"op":"true"}` { t.Errorf("residuals round-trip wrong: %s", got.Residuals["prop1"]) @@ -162,7 +162,7 @@ func TestWriteStep_AppendsOneJsonLine(t *testing.T) { Snapshots: map[string]json.RawMessage{ "ledger.balance": json.RawMessage(`1500`), }, - Action: &Action{Kind: "tap", X: 100, Y: 200}, + NextAction: &Action{Kind: "tap", X: 100, Y: 200}, Violations: []string{"ledgerBalanceMatchesTxns"}, } if err := writer.WriteStep(step); err != nil { @@ -177,7 +177,7 @@ func TestWriteStep_AppendsOneJsonLine(t *testing.T) { if err := json.Unmarshal([]byte(lines[0]), &got); err != nil { t.Fatalf("invalid JSONL line: %v\n%s", err, lines[0]) } - if got.Index != 1 || got.Screen != "customer_ledger" || got.Action.X != 100 || got.Violations[0] != "ledgerBalanceMatchesTxns" { + if got.Index != 1 || got.Screen != "customer_ledger" || got.NextAction.X != 100 || got.Violations[0] != "ledgerBalanceMatchesTxns" { t.Errorf("step round-trip wrong: %+v", got) } }