A-278: seatlist.Definition is the one seat-definition function AnswerSeat takes

The definition of a seat on the list a part follows, read through the part's reader at each call: none until the list
is read, none for a seat the list does not hold. Every holder passes it instead of writing its own.

Builds: design 47 G A-278, A-186, A-179

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
2026-11-12 11:39:57 +01:00
parent 208acf939b
commit 4922bcbf44
2 changed files with 31 additions and 0 deletions
+17
View File
@@ -6,6 +6,7 @@ import (
stdio "git.novox.be/novox/mesh-sdk/go"
"git.novox.be/novox/mesh-sdk/go/catalogue"
"git.novox.be/novox/mesh-sdk/go/seatdef"
)
// A part that reads the seat list wires its reader one way (novox/hq ADR 0636 §1, §7): started from the bootstrapped
@@ -57,6 +58,22 @@ func (p *Part) Reader() *Reader {
return p.reader.Load()
}
// Definition is the seat-definition function process.Conn.AnswerSeat takes, written once for every holder (design 47 G
// A-278, A-186): the definition of seat on the list the part follows, read at each call through reader (a Part's
// Reader, or a part's own reader), none until the list is read and none for a seat the list does not hold.
func Definition(reader func() *Reader, seat string) func() (seatdef.Definition, bool) {
return func() (seatdef.Definition, bool) {
r := reader()
if r == nil || !r.Status().Heard {
return seatdef.Definition{}, false
}
r.mu.Lock()
defer r.mu.Unlock()
d, ok := r.defs[seat]
return d, ok
}
}
// MayAct is the reader's MayAct, false before it is started.
func (p *Part) MayAct(seats ...string) bool {
r := p.Reader()
+14
View File
@@ -201,11 +201,25 @@ func TestTheBootstrapIsHeldAndNothingNewIsActedOnUntilTheSeatAnswers(t *testing.
t.Fatalf("waiting: MayAct(%v) = %v, want %v", a.seats, got, a.want)
}
}
// A-278: the seat-definition function AnswerSeat takes answers none until the list is read, and none without a reader.
reader := func() *Reader { return r }
if _, ok := Definition(reader, "node-engine")(); ok {
t.Fatal("Definition answered a bootstrapped definition before the seat list was read")
}
if _, ok := Definition(func() *Reader { return nil }, "node-engine")(); ok {
t.Fatal("Definition answered with no reader")
}
owner.down = false
owner.table = map[string]string{"node-b": def("node-b", "node", "put")}
if err := r.Reload(); err != nil {
t.Fatal(err)
}
if d, ok := Definition(reader, "node-b")(); !ok || d.Seat != "node-b" {
t.Fatalf("Definition(node-b) after the list was read = %+v, %v, want node-b's", d, ok)
}
if _, ok := Definition(reader, "node-files")(); ok {
t.Fatal("Definition answered a seat the list does not hold")
}
if st := r.Status(); !st.Heard || len(st.Waiting) != len(boot) || st.LastError != "" || st.Revision != 7 {
t.Fatalf("status after the seat answered %+v: want heard, the bootstrap's seats it does not hold still waiting, no error, revision 7", st)
}