diff --git a/cmd/mesh-controller/seats.go b/cmd/mesh-controller/seats.go index b4af7cc..7cccc55 100644 --- a/cmd/mesh-controller/seats.go +++ b/cmd/mesh-controller/seats.go @@ -156,18 +156,37 @@ func handOver(ctx context.Context, seatName, to string) error { if m == nil { return fmt.Errorf("%s is assigned but not in the catalogue, which should not happen", module) } - if err := catalogue.CanHold(*m, seat); err != nil { - return fmt.Errorf("%s cannot hold %s: %w", module, seat.Name, err) + var was string + holdings, err := inv.Holdings(ctx) + if err != nil { + return err + } + for _, h := range holdings { + if hs, ok := catalogue.SeatNamed(h.Claim); ok && hs.Name == seat.Name { + was = h.Node + } } - var was string - if holdings, err := inv.Holdings(ctx); err == nil { - for _, h := range holdings { - if hs, ok := catalogue.SeatNamed(h.Claim); ok && hs.Name == seat.Name { - was = h.Node - } + // **Recording who already holds the seat is not making a new holder, and is not judged like + // one.** On a mesh that predates the record, the first handover has to begin by writing down + // the standing holder — otherwise the next holder cannot be assigned beside it, because two + // eligible claimants with nothing on record are refused. That standing holder may no longer + // satisfy what the seat delivers (the row moved under it, on purpose, as ADR 0131's first step), + // and it holds regardless: derivation never read that column. So when nothing is on record and + // the named assignment is the one holding by derivation, only the claim itself is checked here. + // Every *change* of holder is judged in full. + claimsIt := false + for _, c := range m.Claims { + if cs, ok := catalogue.SeatNamed(c.Name); ok && cs.Name == seat.Name && c.At() == seat.Scope { + claimsIt = true } } + if was == "" && claimsIt { + fmt.Printf("nothing was on record for %s; recording %s on %s as its standing holder\n", + seat.Name, module, nodeName) + } else if err := catalogue.CanHold(*m, seat); err != nil { + return fmt.Errorf("%s cannot hold %s: %w", module, seat.Name, err) + } if err := inv.HoldSeat(ctx, seat.Name, seat.Scope, nodeName, module); err != nil { return err }