A constraint propagates knowledge in either direction.
Connectors remember values and their informants, so an adder relation derives any missing term and retracts knowledge that depended on a forgotten value.
Guiding question
How can one relation react correctly no matter which two values arrive first?
Represent a connector value, informant, and constraint list explicitly
Notify connected constraints when knowledge appears or disappears
Use an adder relation to derive any one of its three values
Retract dependent knowledge without erasing independent user values
Each connector stores whether it has a value, the value, who supplied it, and the constraints to notify. set-value! accepts the first value and sends new-value to every constraint except the setter. The adder can therefore compute total from two terms or either term from the total and the other term.
forget-value! succeeds only when the retractor is the stored informant. When the user forgets total, the adder retracts right because it supplied that derived value, but it cannot retract the independently supplied left value. Supplying a new right value then derives a new total through the same relation.
The first program returns (10 32 42). The second returns ((10 32 42) (#t #f #f) 15).
Trace focus
Follow each connector notification to the adder. In the second run, distinguish the user-owned left value from the adder-owned right value, then watch the lost-value message retract only the derived path before a new total propagates.
Try it yourself
Change the program and compare the result.
In the second program, forget left instead of total. Predict which connectors lose values and which user-supplied value remains.
Show hint
A connector accepts a retraction only from its current informant. The adder can retract values that it supplied, not values supplied by user.