Support legacy fields
diff --git a/ast/rewrite_test.go b/ast/rewrite_test.go
new file mode 100644
index 0000000..63f5e53
--- /dev/null
+++ b/ast/rewrite_test.go
@@ -0,0 +1,229 @@
+package ast
+
+import (
+	"encoding/json"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+)
+
+func TestRewriteUnmarshalJSON(t *testing.T) {
+	tests := []struct {
+		name     string
+		input    string
+		expected Rewrite
+	}{
+		{
+			name: "Standard rewrite with editor and original",
+			input: `{
+				"@type": "koral:rewrite",
+				"editor": "termMapper",
+				"operation": "operation:mapping",
+				"scope": "foundry",
+				"original": {
+					"@type": "koral:term",
+					"foundry": "opennlp",
+					"key": "PIDAT",
+					"layer": "p",
+					"match": "match:eq"
+				}
+			}`,
+			expected: Rewrite{
+				Editor:    "termMapper",
+				Operation: "operation:mapping",
+				Scope:     "foundry",
+				Original: map[string]any{
+					"@type":   "koral:term",
+					"foundry": "opennlp",
+					"key":     "PIDAT",
+					"layer":   "p",
+					"match":   "match:eq",
+				},
+			},
+		},
+		{
+			name: "Legacy rewrite with source instead of editor",
+			input: `{
+				"@type": "koral:rewrite",
+				"source": "legacy-mapper",
+				"operation": "operation:mapping",
+				"scope": "foundry",
+				"src": "legacy-source"
+			}`,
+			expected: Rewrite{
+				Editor:    "legacy-mapper",
+				Operation: "operation:mapping",
+				Scope:     "foundry",
+				Src:       "legacy-source",
+			},
+		},
+		{
+			name: "Legacy rewrite with origin instead of original/src",
+			input: `{
+				"@type": "koral:rewrite",
+				"editor": "termMapper",
+				"operation": "operation:mapping",
+				"scope": "foundry",
+				"origin": "legacy-origin"
+			}`,
+			expected: Rewrite{
+				Editor:    "termMapper",
+				Operation: "operation:mapping",
+				Scope:     "foundry",
+				Src:       "legacy-origin",
+			},
+		},
+		{
+			name: "Precedence test: editor over source",
+			input: `{
+				"@type": "koral:rewrite",
+				"editor": "preferred-editor",
+				"source": "legacy-source",
+				"operation": "operation:mapping"
+			}`,
+			expected: Rewrite{
+				Editor:    "preferred-editor",
+				Operation: "operation:mapping",
+			},
+		},
+		{
+			name: "Precedence test: original over src over origin",
+			input: `{
+				"@type": "koral:rewrite",
+				"editor": "termMapper",
+				"operation": "operation:mapping",
+				"original": "preferred-original",
+				"src": "middle-src",
+				"origin": "lowest-origin"
+			}`,
+			expected: Rewrite{
+				Editor:    "termMapper",
+				Operation: "operation:mapping",
+				Original:  "preferred-original",
+			},
+		},
+		{
+			name: "Precedence test: src over origin when no original",
+			input: `{
+				"@type": "koral:rewrite",
+				"editor": "termMapper",
+				"operation": "operation:mapping",
+				"src": "preferred-src",
+				"origin": "lowest-origin"
+			}`,
+			expected: Rewrite{
+				Editor:    "termMapper",
+				Operation: "operation:mapping",
+				Src:       "preferred-src",
+			},
+		},
+		{
+			name: "Only legacy fields",
+			input: `{
+				"@type": "koral:rewrite",
+				"source": "legacy-editor",
+				"operation": "operation:mapping",
+				"origin": "legacy-origin",
+				"_comment": "Legacy rewrite"
+			}`,
+			expected: Rewrite{
+				Editor:    "legacy-editor",
+				Operation: "operation:mapping",
+				Src:       "legacy-origin",
+				Comment:   "Legacy rewrite",
+			},
+		},
+		{
+			name: "Mixed with comment",
+			input: `{
+				"@type": "koral:rewrite",
+				"editor": "termMapper",
+				"operation": "operation:mapping",
+				"scope": "foundry",
+				"src": "original-source",
+				"_comment": "This is a comment"
+			}`,
+			expected: Rewrite{
+				Editor:    "termMapper",
+				Operation: "operation:mapping",
+				Scope:     "foundry",
+				Src:       "original-source",
+				Comment:   "This is a comment",
+			},
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			var rewrite Rewrite
+			err := json.Unmarshal([]byte(tt.input), &rewrite)
+			require.NoError(t, err)
+			assert.Equal(t, tt.expected, rewrite)
+		})
+	}
+}
+
+func TestRewriteArrayUnmarshal(t *testing.T) {
+	// Test unmarshaling an array of rewrites with mixed legacy and modern fields
+	input := `[
+		{
+			"@type": "koral:rewrite",
+			"editor": "termMapper",
+			"operation": "operation:mapping",
+			"original": "modern-original"
+		},
+		{
+			"@type": "koral:rewrite",
+			"source": "legacy-editor",
+			"operation": "operation:legacy",
+			"origin": "legacy-origin"
+		}
+	]`
+
+	var rewrites []Rewrite
+	err := json.Unmarshal([]byte(input), &rewrites)
+	require.NoError(t, err)
+	require.Len(t, rewrites, 2)
+
+	// Check first rewrite (modern)
+	assert.Equal(t, "termMapper", rewrites[0].Editor)
+	assert.Equal(t, "operation:mapping", rewrites[0].Operation)
+	assert.Equal(t, "modern-original", rewrites[0].Original)
+
+	// Check second rewrite (legacy)
+	assert.Equal(t, "legacy-editor", rewrites[1].Editor)
+	assert.Equal(t, "operation:legacy", rewrites[1].Operation)
+	assert.Equal(t, "legacy-origin", rewrites[1].Src)
+}
+
+func TestRewriteMarshalJSON(t *testing.T) {
+	// Test that marshaling works correctly and maintains the modern field names
+	rewrite := Rewrite{
+		Editor:    "termMapper",
+		Operation: "operation:mapping",
+		Scope:     "foundry",
+		Src:       "source-value",
+		Comment:   "Test comment",
+		Original:  "original-value",
+	}
+
+	data, err := json.Marshal(rewrite)
+	require.NoError(t, err)
+
+	// Parse back to verify structure
+	var result map[string]any
+	err = json.Unmarshal(data, &result)
+	require.NoError(t, err)
+
+	assert.Equal(t, "termMapper", result["editor"])
+	assert.Equal(t, "operation:mapping", result["operation"])
+	assert.Equal(t, "foundry", result["scope"])
+	assert.Equal(t, "source-value", result["src"])
+	assert.Equal(t, "Test comment", result["_comment"])
+	assert.Equal(t, "original-value", result["original"])
+
+	// Ensure legacy fields are not present in output
+	assert.NotContains(t, result, "source")
+	assert.NotContains(t, result, "origin")
+}