Garnet had a lot of cool ideas in it, especially its constraints and prototype based object system.
A few years ago I wrote up a description of a similar system called OpenLaszlo, and how OpenLaszlo's constraint system compared with Garnet's constraint system. Garnet had a lazy "pull" constraint system, while Laszlo had an event/delegate based "push" system. Each used a compiler to automatically determine the dependencies of constraint expressions.
Constraints and Prototypes in Garnet and Laszlo
The problem we ran into with supporting PostScript with Garnet is that we wanted to use Display PostScript, but Garnet was using CLX, the Common Lisp X Protocol library which was of course totally written purely in Lisp.
Of course CLX had no way to use any client side libraries that depended on XLib itself. I'd steer clear of using anything that depends on CLX for anything modern. (Does CLX still even exist?)
Brad Myers produced "All the Widgets," which must have some Garnet demos in there somewhere! 
 All the Widgets, sponsored by the ACM CHI 1990 conference, to tell the history of widgets up until then:
"Constraints are like structured programming for variables"
Love it! Having been very interested in constraint programming and also dabbled a bit here and there, what do you think is holding back constraint programming?
All the constraints. ;)
As you mentioned, there are tricky two-way mathematical constraints, like Sutherland's Sketchpad  and descendants , and Gosling's PhD Thesis , where the system understands the constraint expressions mathematically and transforms them algebraically.
 Ivan Sutherland's Sketchpad:
 Geometer's Sketchpad:
 Algebraic Constraints; James Gosling; CMU CS Department PhD Thesis:
And there are simpler one-way data flow constraints like Apple's KVO notification , Garnet's KR based constraints , and OpenLaszlo's event/delegate based constraints .
 Introduction to Key-Value Observing Programming Guide:
 KR: Constraint-Based Knowledge Representation:
 Oliver Steel: Instance-First Development:
As you pointed out, KVO constraints simply say that object.x = otherObject.y, so there's not much to them.
I think one thing holding back constraint programming is that they require an interpreter or compiler to understand them, or the programmer to write code in a constrained syntax.
Garnet's KR constraints are written as Lisp expressions implemented by Lisp macros, that parse the expressions and recognize certain expressions like "gvl" for "get value", and named path expressions. KR wires up the dependency graph based on that information, and marks the constraint as invalid if any of the links along the dependency path change, as well as when any of the final values the expressions reference change. But it doesn't understand the mathematical expressions themselves. At the time I was working on it, it didn't know hot to figure out which branches of conditional expressions mattered, so it would assume it depended on everything in the expression. (i.e. like the C expression "size = window.landscape ? parent.width : parent.height" -- if window.landscape is true, it depends on parent.width, else it depends on parent.height, but ). It only recalculates the constraint values lazily when you read them. ("pull" constraints).
OpenLaszlo constraints used a "push" model of propagating all dependent changes forward when you called "setValue", because that was the best trade-off at the time for speed and usability and how it was intended to be used. But with getters and setters you could implement a more convenient constraint system that didn't put so many constraints on the programmer and how you use them.