@jeffmccune I followed up this morning after the post patrick referenced and this exchange:

10:11 <+pcarlisle> so this may sound strange, but my understanding is basically luke's, i.e. contain effectively calls include and then adds a containment edge
10:12 <+pcarlisle> eric0: you implied in your email you wanted to go with not calling include, which i don't understand
10:15 <+zaphod42> pcarlisle: my understanding was the same. contain(x) = { include(x); if not edge?(parent, x) then add_edge(parent, x) end }
10:15 <+zaphod42> pcarlisle: actually contain(x) = { include(x); if edge(parent, x) then fail "cannot contain twice" else add_edge(parent, x) end }
10:18 <+eric0> it's highly likely i was wrong
10:22 <ashp> as an end user I would be surprised and annoyed if contain didn't do an include along the way
10:53 <+eric0> re: contains, sounds like everybody agrees and i'm wrong; i'll post a follow up