What happens
A live mutation that draws an edge from an interior node of a sealed hive to the hive's own root — add_edges with to: "." and a constant set_hop: {"route": "error"} — is refused by the hive_contract validator:
sends hop.route='error' into hive <member>, which does not accept that lane
The very same edge ships in templates/member (the catch-all ./channels -> . on error, GH #598) and instantiates at boot with a warning at most. So the boot path and the mutation path disagree about one edge: an edge from inside a hive to . is an exit (the message leaves through the hive's rim), but the validator reads it as an entry into the hive and checks the hive's accepts list against it.
Measured (2026-09-06, GH #598 rewire of two running colonies)
Ask
hive_contract should classify an edge by direction the way the router does: from interior, to == "." (or the hive's own path) is an exit and is checked against emits, not accepts. A regression test: the shipped member catch-all edge, applied as a live add_edges to a grown member, must commit, and the same body must still be refused when it truly enters a hive that does not accept the lane.
What happens
A live mutation that draws an edge from an interior node of a sealed hive to the hive's own root —
add_edgeswithto: "."and a constantset_hop: {"route": "error"}— is refused by thehive_contractvalidator:The very same edge ships in
templates/member(the catch-all./channels -> .onerror, GH #598) and instantiates at boot with a warning at most. So the boot path and the mutation path disagree about one edge: an edge from inside a hive to.is an exit (the message leaves through the hive's rim), but the validator reads it as an entry into the hive and checks the hive'sacceptslist against it.Measured (2026-09-06, GH #598 rewire of two running colonies)
meclaw 0.31.0+ apps rim, membermarcus) and the demo colony (memberdemo): theremove_edgeshalf of the Endless loop that costs money: displayinvalid_viewreceipt →in_turn(kind receipt) → assistant answers in prose → display refuses again (44 brain calls in 6 min) #598 fix (drop thereceipt -> in_turnre-stamp) committed on both; theadd_edgeshalf (widen./channels -> .to carryreceiptout onerror) was refused with the line above on both.errormessage leaving the level. The loop is gone either way (the text-turn proof ran at 3 resp. 4 brain calls), but the two colonies do not carry the shipped topology.Ask
hive_contractshould classify an edge by direction the way the router does:frominterior,to == "."(or the hive's own path) is an exit and is checked againstemits, notaccepts. A regression test: the shipped member catch-all edge, applied as a liveadd_edgesto a grown member, must commit, and the same body must still be refused when it truly enters a hive that does not accept the lane.