The first handover records the standing holder without re-judging it

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.
This commit is contained in:
2026-09-27 23:34:40 +02:00
parent ae7fb520d7
commit 4c41628b20
+27 -8
View File
@@ -156,18 +156,37 @@ func handOver(ctx context.Context, seatName, to string) error {
if m == nil { if m == nil {
return fmt.Errorf("%s is assigned but not in the catalogue, which should not happen", module) return fmt.Errorf("%s is assigned but not in the catalogue, which should not happen", module)
} }
if err := catalogue.CanHold(*m, seat); err != nil { var was string
return fmt.Errorf("%s cannot hold %s: %w", module, seat.Name, err) 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 // **Recording who already holds the seat is not making a new holder, and is not judged like
if holdings, err := inv.Holdings(ctx); err == nil { // one.** On a mesh that predates the record, the first handover has to begin by writing down
for _, h := range holdings { // the standing holder — otherwise the next holder cannot be assigned beside it, because two
if hs, ok := catalogue.SeatNamed(h.Claim); ok && hs.Name == seat.Name { // eligible claimants with nothing on record are refused. That standing holder may no longer
was = h.Node // 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 { if err := inv.HoldSeat(ctx, seat.Name, seat.Scope, nodeName, module); err != nil {
return err return err
} }