From 4c41628b20469824aba82fa82c0cda24928d4fc8 Mon Sep 17 00:00:00 2001 From: jochen Date: Sun, 27 Sep 2026 23:34:40 +0200 Subject: [PATCH] The first handover records the standing holder without re-judging it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On a mesh that predates the record, every handover has to begin by writing down who already holds the seat — otherwise the next holder cannot be assigned beside it, because two eligible claimants with nothing on record are refused. Found on the live mesh minutes after 0040 moved the bus seat's row: the standing holder no longer satisfies what the seat delivers, on purpose, and so could not be recorded, and so nothing could stand beside it. Recording who already holds is not making a new holder. Derivation never read what the seat delivers, so the standing holder holds regardless; when nothing is on record and the named assignment claims the seat at its scope, only that claim is checked. Every change of holder is still judged in full. --- cmd/mesh-controller/seats.go | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) 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 } -- 2.54.0