package main import ( "reflect" "testing" "github.com/novox/mesh-controller/internal/inventory" ) // novox/hq issue 309, replayed with only what orderOf had before its fix, so it can be laid over the older // commit. The group `feat/a-machine-joins-through-the-tunnel` (2026-10-08): the controller's pull request // moved the controller and the build agent, the node-engine's moved the node-engine, the lab's moved // nothing. The build agent builds the node-engine (built by: the controller's member first), and the // node-engine goes before the controller (engine before controller: the node-engine's member first). Both // rules applied to one pair in opposite directions, and the group was rejected as a cycle; the person merged // the controller first by hand. A rule read from the graph outranks the rollout default, so the group is // ordered, the controller's member first. func TestReplay309(t *testing.T) { members := []orderMember{ {ID: "novox/mesh-controller@8bbfdb53db2b", Repository: "novox/mesh-controller", Number: 132}, {ID: "novox/mesh-host@86cbebd10f8a", Repository: "novox/mesh-host", Number: 52}, {ID: "novox/mesh-lab@e80a4b1642bf", Repository: "novox/mesh-lab", Number: 61}, } reach := map[string]orderReach{ "novox/mesh-controller@8bbfdb53db2b": {Moved: []string{"build-agent", "mesh-controller", "route-proxy"}, Manifests: []string{"module.json"}}, "novox/mesh-host@86cbebd10f8a": {Moved: []string{"mesh-host"}}, "novox/mesh-lab@e80a4b1642bf": {}, } // Every source-built module is built by the build seat's holder; the holder follows the controller. edges := []inventory.Edge{ {From: "build-agent", To: "mesh-controller", Kind: inventory.EdgeWorkerOf}, {From: "mesh-controller", To: "build-agent", Kind: inventory.EdgeBuiltBy}, {From: "mesh-host", To: "build-agent", Kind: inventory.EdgeBuiltBy}, {From: "route-proxy", To: "build-agent", Kind: inventory.EdgeBuiltBy}, } got := orderOf(members, reach, edges) if len(got.Cycle) > 0 { t.Fatalf("the group is refused as a cycle %v; pairs %+v", got.Cycle, got.Pairs) } want := []string{"novox/mesh-controller@8bbfdb53db2b", "novox/mesh-host@86cbebd10f8a", "novox/mesh-lab@e80a4b1642bf"} if !reflect.DeepEqual(got.Order, want) { t.Fatalf("ordered %v, wanted %v; pairs %+v", got.Order, want, got.Pairs) } for _, p := range got.Pairs { if p.Before == want[1] && p.After == want[0] { t.Fatalf("a pair that lost still stands: %+v", p) } } }