diff --git a/internal/agent/preview.go b/internal/agent/preview.go
index 67f69894a..d89ece1a7 100644
--- a/internal/agent/preview.go
+++ b/internal/agent/preview.go
@@ -5,7 +5,7 @@ import (
"strings"
)
-var reTransientUserBlock = regexp.MustCompile(`(?s)^\s*<(?:reasoning-language|memory-update|background-jobs)>.*?(?:reasoning-language|memory-update|background-jobs)>\s*\n?`)
+var reTransientUserBlock = regexp.MustCompile(`(?s)^\s*<(?:reasoning-language|memory-update|background-jobs|active-goal)>.*?(?:reasoning-language|memory-update|background-jobs|active-goal)>\s*\n?`)
// StripTransientUserBlocks removes controller-injected transient XML blocks
// from persisted user messages before deriving display text, previews, or
diff --git a/internal/agent/preview_test.go b/internal/agent/preview_test.go
new file mode 100644
index 000000000..f0b8a30e5
--- /dev/null
+++ b/internal/agent/preview_test.go
@@ -0,0 +1,23 @@
+package agent_test
+
+import (
+ "reasonix/internal/agent"
+ "testing"
+)
+
+func TestStripTransientBlocksActiveGoal(t *testing.T) {
+ tests := []struct {
+ in, want string
+ }{
+ {"\nFix all bugs\n\n\nfix the auth bug", "fix the auth bug"},
+ {"\nuse Chinese\n\n\n\nDo X\n\n\nhelp me", "help me"},
+ {"\n- note\n\n\n\nGoal text\n\n\ndo it", "do it"},
+ {"\n\nmulti-line\ngoal\n\n\nuser text", "user text"},
+ }
+ for _, tt := range tests {
+ got := agent.StripTransientUserBlocks(tt.in)
+ if got != tt.want {
+ t.Errorf("StripTransientUserBlocks(%q) = %q, want %q", tt.in, got, tt.want)
+ }
+ }
+}