From bdd79ad5853d8d921cd68555f2c921526d1276bd Mon Sep 17 00:00:00 2001 From: claude Date: Sun, 6 Sep 2026 13:50:30 +0400 Subject: [PATCH] mavend: carry ResolvedBy through dialogue Slots bridge Add ResolvedBy to dialogue.Slots and the toDialogueSlots/ applyDialogueSlots converters. Skip reflect-type check for this field in parity test (dialogue cannot import router: import cycle). --- cmd/mavend/followup.go | 20 +++++++++++--------- cmd/mavend/slotsparity_test.go | 25 ++++++++++++++++--------- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/cmd/mavend/followup.go b/cmd/mavend/followup.go index 1a818d6..3c60410 100644 --- a/cmd/mavend/followup.go +++ b/cmd/mavend/followup.go @@ -72,15 +72,16 @@ func dialogueIDOf(ctx context.Context) string { // toDialogueSlots projects the router's slots onto the dialogue layer's copy. func toDialogueSlots(s router.Slots) dialogue.Slots { return dialogue.Slots{ - Time: s.Time, - HasTime: s.HasTime, - Key: s.Key, - Value: s.Value, - HasKey: s.HasKey, - Text: s.Text, - Fn: s.Fn, - Args: s.Args, - HasFn: s.HasFn, + Time: s.Time, + HasTime: s.HasTime, + Key: s.Key, + Value: s.Value, + HasKey: s.HasKey, + Text: s.Text, + Fn: s.Fn, + Args: s.Args, + HasFn: s.HasFn, + ResolvedBy: string(s.ResolvedBy), } } @@ -90,6 +91,7 @@ func applyDialogueSlots(base router.Slots, d dialogue.Slots) router.Slots { base.Key, base.Value, base.HasKey = d.Key, d.Value, d.HasKey base.Text = d.Text base.Fn, base.Args, base.HasFn = d.Fn, d.Args, d.HasFn + base.ResolvedBy = router.ActionResolutionMethod(d.ResolvedBy) return base } diff --git a/cmd/mavend/slotsparity_test.go b/cmd/mavend/slotsparity_test.go index 1cfb5b0..00511b1 100644 --- a/cmd/mavend/slotsparity_test.go +++ b/cmd/mavend/slotsparity_test.go @@ -31,6 +31,12 @@ func TestSlotsParity(t *testing.T) { t.Errorf("router.Slots.%s (%s) missing from dialogue.Slots", name, typ) continue } + // ResolvedBy is ActionResolutionMethod in router and string in dialogue + // (dialogue cannot import router: import cycle). The underlying type is + // string in both; skip the reflect-type check for this field. + if name == "ResolvedBy" { + continue + } if dt != typ { t.Errorf("field %s: router has %s, dialogue has %s", name, typ, dt) } @@ -47,15 +53,16 @@ func TestSlotsParity(t *testing.T) { // populated value and compare. func TestSlotsRoundTrip(t *testing.T) { full := router.Slots{ - Time: time.Date(2026, 8, 2, 11, 0, 0, 0, time.UTC), - HasTime: true, - Fn: "restart", - Args: []string{"nginx"}, - HasFn: true, - Key: "water", - Value: `"drank"`, - HasKey: true, - Text: "выпил воды", + Time: time.Date(2026, 8, 2, 11, 0, 0, 0, time.UTC), + HasTime: true, + Fn: "restart", + Args: []string{"nginx"}, + HasFn: true, + ResolvedBy: router.ActionResolutionGrammarMatcher, + Key: "water", + Value: `"drank"`, + HasKey: true, + Text: "выпил воды", } // Every field must be non-zero, or the round-trip proves nothing. rv := reflect.ValueOf(full)