Fix layer precedence and document precedences

Change-Id: I7fdc9f9122d7e723f98674a9f9e3010c38118ba9
diff --git a/ast/ast.go b/ast/ast.go
index 2da55b8..0f1c858 100644
--- a/ast/ast.go
+++ b/ast/ast.go
@@ -309,6 +309,42 @@
 	}
 }
 
+// ApplyFoundryAndLayerOverridesWithPrecedence applies foundry and layer overrides while respecting precedence:
+// 1. Mapping rule foundry/layer (highest priority - don't override if already set)
+// 2. Passed overwrite foundry/layer (from MappingOptions)
+// 3. Mapping list foundry/layer (lowest priority - defaults)
+func ApplyFoundryAndLayerOverridesWithPrecedence(node Node, foundry, layer string) {
+	if node == nil {
+		return
+	}
+
+	switch n := node.(type) {
+	case *Term:
+		// Only override if the term doesn't already have explicit values (respecting precedence)
+		if foundry != "" && n.Foundry == "" {
+			n.Foundry = foundry
+		}
+		if layer != "" && n.Layer == "" {
+			n.Layer = layer
+		}
+	case *TermGroup:
+		for _, op := range n.Operands {
+			ApplyFoundryAndLayerOverridesWithPrecedence(op, foundry, layer)
+		}
+	case *Token:
+		if n.Wrap != nil {
+			ApplyFoundryAndLayerOverridesWithPrecedence(n.Wrap, foundry, layer)
+		}
+	case *CatchallNode:
+		if n.Wrap != nil {
+			ApplyFoundryAndLayerOverridesWithPrecedence(n.Wrap, foundry, layer)
+		}
+		for _, op := range n.Operands {
+			ApplyFoundryAndLayerOverridesWithPrecedence(op, foundry, layer)
+		}
+	}
+}
+
 // RestrictToObligatory takes a replacement node from a mapping rule and reduces the boolean structure
 // to only obligatory operations by removing optional OR-relations and keeping required AND-relations.
 // It also applies foundry and layer overrides like ApplyFoundryAndLayerOverrides().
@@ -336,6 +372,25 @@
 	return restricted
 }
 
+// RestrictToObligatoryWithPrecedence is like RestrictToObligatory but respects precedence rules
+// when applying foundry and layer overrides
+func RestrictToObligatoryWithPrecedence(node Node, foundry, layer string) Node {
+	if node == nil {
+		return nil
+	}
+
+	// First, clone and restrict to obligatory operations
+	cloned := node.Clone()
+	restricted := restrictToObligatoryRecursive(cloned)
+
+	// Then apply foundry and layer overrides with precedence to the smaller, restricted tree
+	if restricted != nil {
+		ApplyFoundryAndLayerOverridesWithPrecedence(restricted, foundry, layer)
+	}
+
+	return restricted
+}
+
 // restrictToObligatoryRecursive performs the actual restriction logic
 func restrictToObligatoryRecursive(node Node) Node {
 	if node == nil {