From d2685434576ed3e7b09913c02a64276a0af410f2 Mon Sep 17 00:00:00 2001 From: Henrique Costa Date: Thu, 30 Apr 2026 14:58:06 +0200 Subject: [PATCH] fix: emit loop captions during microflow describe Symptom: describe emitted @caption for action activities and split activities, but captions stored on LoopedActivity objects were omitted. Root cause: emitObjectAnnotations did not handle LoopedActivity.Caption even though the builder already preserves captions for loop and while statements. Fix: emit a quoted @caption annotation for LoopedActivity before attached @annotation lines, matching the existing ExclusiveSplit and InheritanceSplit handling. Tests: added a focused emitObjectAnnotations regression covering loop captions with apostrophe and newline escaping; ran make build, targeted executor tests, make test, and make lint-go. --- mdl/executor/cmd_microflows_show_helpers.go | 3 +++ .../cmd_microflows_show_helpers_test.go | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/mdl/executor/cmd_microflows_show_helpers.go b/mdl/executor/cmd_microflows_show_helpers.go index 32460732..d63cb478 100644 --- a/mdl/executor/cmd_microflows_show_helpers.go +++ b/mdl/executor/cmd_microflows_show_helpers.go @@ -462,6 +462,9 @@ func emitObjectAnnotations( if split, ok := obj.(*microflows.InheritanceSplit); ok && split.Caption != "" { *lines = append(*lines, indentStr+fmt.Sprintf("@caption %s", mdlQuote(split.Caption))) } + if loop, ok := obj.(*microflows.LoopedActivity); ok && loop.Caption != "" { + *lines = append(*lines, indentStr+fmt.Sprintf("@caption %s", mdlQuote(loop.Caption))) + } // @annotation (attached Annotation objects) if annotationsByTarget != nil { diff --git a/mdl/executor/cmd_microflows_show_helpers_test.go b/mdl/executor/cmd_microflows_show_helpers_test.go index b57efbad..cd02c4d7 100644 --- a/mdl/executor/cmd_microflows_show_helpers_test.go +++ b/mdl/executor/cmd_microflows_show_helpers_test.go @@ -160,6 +160,25 @@ func TestEmitObjectAnnotations_EscapesMultilineText(t *testing.T) { } } +func TestEmitObjectAnnotations_LoopCaption(t *testing.T) { + obj := µflows.LoopedActivity{ + BaseMicroflowObject: microflows.BaseMicroflowObject{ + BaseElement: model.BaseElement{ID: mkID("loop")}, + Position: model.Point{X: 100, Y: 200}, + }, + Caption: "Loop owner's\ncaption", + } + + var lines []string + // Pass nil flow maps — @anchor emission is intentionally suppressed here. + emitObjectAnnotations(obj, &lines, "", nil, nil, nil, nil) + + got := strings.Join(lines, "\n") + if !strings.Contains(got, "@caption 'Loop owner''s\\ncaption'") { + t.Fatalf("expected escaped loop caption, got:\n%s", got) + } +} + func TestPrependFreeAnnotationLines_ModelAnnotationsStayFree(t *testing.T) { oc := µflows.MicroflowObjectCollection{ Objects: []microflows.MicroflowObject{