The principal square root function is a logically, mathematically, symbolically and numerically perfectly fine function. Using the names sqrt/Sqrt to denote anything else is a mistake. Not because other notions of square root aren’t useful too, but because this convention is already firmly established. If you want a function that returns a set, call it something else (all_square_roots(x) or whatever).
The more general issue here is that computer algebra systems historically are very confused about what it means to solve something. Does solve() return some particular solution, the set of solutions, a set containing some of the solutions, a superset of the solutions (possibly containing spurious solutions), real solutions, complex solutions, or something random depending on context or the phase of the moon? I’ve seen all combinations.
This confusion essentially goes away if you build symbolic sets with well-typed quantifiers into the system. If you want to solve x^2 = y, write down S = \{x : x \in \mathbb{C} \land x^2 = y \} or S = \{x : x \in \mathbb{R} \land x \ge 0 \land x^2 = y \} or something else, depending on what you mean. Now various notions of solving can be reduced to computations on the set S: checking its cardinality, extracting an arbitrary element, iterating over the elements, computing some superset, taking the intersection with another set, etc. To keep things convenient for users, you may want unique_solution(), any_solution() and all_solutions() functions or something similar.
There is actually nothing inherently wrong with simplifying sqrt(x^2) → x or solving x^2 = y → x = sqrt(x) as purely formal operations on formal symbolic expressions. You just have to remember that these are formal operations which don’t commute with evaluation for x \in \mathbb{R}, say. When we do mathematics by hand, we often ignore conditions and check that the result makes sense in the end. The traditional CAS design approach mimics human operation but leaves the final checking to the user. This is clearly very useful in many cases, but it makes it seriously difficult to write correct complex programs that compose operations (where the user can’t realistically check each step). I’m convinced that it’s possible to do better; there’s no need to throw out the classical heuristic symbolic manipulation completely, but it should be a complement to and not a substitute for correct domain-aware rewriting. There are some parallels with floating-point versus interval arithmetic here (including the fact that floating-point solutions much like heuristic symbolic solutions sometimes can be checked a posteriori!).
I also completely agree with Oscar Benjamin that automatic evaluation is a mistake. Simple, unevaluated expressions by default are a win-win: easier to implement, easier and more versatile to use (the user can decide precisely which transformations to apply), and more efficient (symbolic expressions are a terrible data structure for algebraic computation). Instead of performing clever and invariably buggy automatic “canonicalization” on expressions, a far better solution is to convert to specialized data structures internally for computations (e.g. polynomial types for expanding or factoring).