From db3f07d277fd81c5aee05cac2bf9947feed6ac53 Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 12 Nov 2026 11:39:57 +0100 Subject: [PATCH] A-278: the assigner, builder, indexer and pipeline runner pass seatlist.Definition to AnswerSeat Their four copies of the seat-definition function go; each passes its seat list part's reader to mesh-sdk's one. Builds: design 47 G A-278, A-186 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h --- .../cmd/mesh-delivery-assigner/main.go | 2 +- .../cmd/mesh-delivery-assigner/seatlist.go | 17 ----------------- .../cmd/mesh-delivery-assigner/seatlist_test.go | 8 ++++---- .../cmd/mesh-delivery-builder/main.go | 2 +- .../cmd/mesh-delivery-builder/seatlist.go | 14 -------------- .../cmd/mesh-delivery-builder/seatlist_test.go | 8 ++++---- .../cmd/mesh-delivery-indexer/main.go | 3 ++- .../cmd/mesh-delivery-indexer/seatlist.go | 15 --------------- .../cmd/mesh-delivery-indexer/seatlist_test.go | 8 ++++---- .../cmd/mesh-delivery-pipeline/verbs.go | 16 +--------------- .../cmd/mesh-delivery-pipeline/verbs_test.go | 8 ++++---- 11 files changed, 21 insertions(+), 80 deletions(-) diff --git a/modules/mesh-delivery-assigner/cmd/mesh-delivery-assigner/main.go b/modules/mesh-delivery-assigner/cmd/mesh-delivery-assigner/main.go index 0dce39a4..d9faf0d0 100644 --- a/modules/mesh-delivery-assigner/cmd/mesh-delivery-assigner/main.go +++ b/modules/mesh-delivery-assigner/cmd/mesh-delivery-assigner/main.go @@ -293,7 +293,7 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro // against the seat's definition it holds (A-186). gate := seatlist.NewPart("assigner", seatListAgainCallers) if inputs != nil { - stopInput, err := said.AnswerSeat(meshwants.Seat, seatDefinition(gate, meshwants.Seat), map[string]process.SeatHandler{meshwants.VerbInput: inputs.verb(conn, buscalls.SeatAckWithin)}) + stopInput, err := said.AnswerSeat(meshwants.Seat, seatlist.Definition(gate.Reader, meshwants.Seat), map[string]process.SeatHandler{meshwants.VerbInput: inputs.verb(conn, buscalls.SeatAckWithin)}) if err != nil { return fmt.Errorf("answering the verb input: %w", err) } diff --git a/modules/mesh-delivery-assigner/cmd/mesh-delivery-assigner/seatlist.go b/modules/mesh-delivery-assigner/cmd/mesh-delivery-assigner/seatlist.go index 2c045320..0b8f66e0 100644 --- a/modules/mesh-delivery-assigner/cmd/mesh-delivery-assigner/seatlist.go +++ b/modules/mesh-delivery-assigner/cmd/mesh-delivery-assigner/seatlist.go @@ -1,9 +1,6 @@ package main import ( - "git.novox.be/novox/mesh-sdk/go/seatdef" - "git.novox.be/novox/mesh-sdk/go/seatlist" - stdio "git.novox.be/novox/mesh-sdk/go" ) @@ -16,17 +13,3 @@ import ( // A call through the mesh MCP server is proved only as its machine's tool runner (.node-tools, issue 627), so // node-tools stands for an operator's session until a session is proved (issue 1966). var seatListAgainCallers = []string{stdio.AnyPerson, "node-tools", "mesh-healers"} - -// seatDefinition is the definition of seat the gate's seat list holds, which the seat's verbs answered here check their -// callers against (process.Conn.AnswerSeat; design 47 G lead answers A-179, A-186): false until the seat mesh-catalog has -// answered the list, so the assigner answers a verb only once its seat list is read, and false for a seat it does not hold. -func seatDefinition(gate *seatlist.Part, seat string) func() (seatdef.Definition, bool) { - return func() (seatdef.Definition, bool) { - r := gate.Reader() - if r == nil || !r.Status().Heard { - return seatdef.Definition{}, false - } - d, ok := r.Definitions()[seat] - return d, ok - } -} diff --git a/modules/mesh-delivery-assigner/cmd/mesh-delivery-assigner/seatlist_test.go b/modules/mesh-delivery-assigner/cmd/mesh-delivery-assigner/seatlist_test.go index 65e7e7e5..992599c2 100644 --- a/modules/mesh-delivery-assigner/cmd/mesh-delivery-assigner/seatlist_test.go +++ b/modules/mesh-delivery-assigner/cmd/mesh-delivery-assigner/seatlist_test.go @@ -98,17 +98,17 @@ func TestTheSeatListIsWiredByTheSDKAlone(t *testing.T) { // A-179, A-186: the definition the verb input's callers are checked against is the seat list's, none before the reader starts // or while the seat mesh-catalog has not answered, and none for a seat the list does not hold. func TestTheAnsweredSeatsDefinitionIsTheSeatListsOnceRead(t *testing.T) { - if _, ok := seatDefinition(seatlist.NewPart("assigner", seatListAgainCallers), "mesh-wants")(); ok { + if _, ok := seatlist.Definition(seatlist.NewPart("assigner", seatListAgainCallers).Reader, "mesh-wants")(); ok { t.Error("a definition is answered before the seat list's reader started") } - if _, ok := seatDefinition(gateOver(t, true), "mesh-wants")(); ok { + if _, ok := seatlist.Definition(gateOver(t, true).Reader, "mesh-wants")(); ok { t.Error("a definition is answered while the seat mesh-catalog has not answered the list") } read := gateOver(t, false) - if d, ok := seatDefinition(read, "mesh-wants")(); !ok || d.Seat != "mesh-wants" { + if d, ok := seatlist.Definition(read.Reader, "mesh-wants")(); !ok || d.Seat != "mesh-wants" { t.Errorf("the read list's mesh-wants is answered as %v, %v", d.Seat, ok) } - if _, ok := seatDefinition(read, "no-such-seat")(); ok { + if _, ok := seatlist.Definition(read.Reader, "no-such-seat")(); ok { t.Error("a seat the list does not hold is answered a definition") } } diff --git a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/main.go b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/main.go index 28b1a2f2..afa9d083 100644 --- a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/main.go +++ b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/main.go @@ -405,7 +405,7 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro b.StepEntry = newEntryWaits(branches, half.manifests).entry // The seat mesh-builds' verb reserved, answered here (A-115, A-127): the reservations, the catalog half's carriers and the seat // mesh-catalog's versions. - stopReserved, err := calls.AnswerSeat(meshbuilds.Seat, seatGate.definition(meshbuilds.Seat), map[string]process.SeatHandler{ + stopReserved, err := calls.AnswerSeat(meshbuilds.Seat, seatlist.Definition(seatGate.Reader, meshbuilds.Seat), map[string]process.SeatHandler{ meshbuilds.VerbReserved: reservedVerb(ctx, reservedReader(ctx, reserved.r.Store), versions.CarriersFrom(versions.EntriesOf(branches)), catalogReleased(calls.Call))}) if err != nil { return fmt.Errorf("answering the verb reserved: %w", err) diff --git a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/seatlist.go b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/seatlist.go index 76a12f0a..7d96edc9 100644 --- a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/seatlist.go +++ b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/seatlist.go @@ -24,17 +24,3 @@ func (g *seatGate) definitions() map[string]seatdef.Definition { } return nil } - -// definition is the definition of seat the list holds, which the seat's verbs answered here check their callers against -// (process.Conn.AnswerSeat; design 47 G lead answers A-179, A-186): false until the seat mesh-catalog has answered the list, so -// the builder answers a verb only once its seat list is read, and false for a seat it does not hold. -func (g *seatGate) definition(seat string) func() (seatdef.Definition, bool) { - return func() (seatdef.Definition, bool) { - r := g.Reader() - if r == nil || !r.Status().Heard { - return seatdef.Definition{}, false - } - d, ok := r.Definitions()[seat] - return d, ok - } -} diff --git a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/seatlist_test.go b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/seatlist_test.go index a5e1d795..ffb25f6e 100644 --- a/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/seatlist_test.go +++ b/modules/mesh-delivery-builder/cmd/mesh-delivery-builder/seatlist_test.go @@ -34,17 +34,17 @@ func TestTheAnsweredSeatsDefinitionIsTheSeatListsOnceRead(t *testing.T) { } return g } - if _, ok := newSeatGate().definition(seatlist.Seat)(); ok { + if _, ok := seatlist.Definition(newSeatGate().Reader, seatlist.Seat)(); ok { t.Error("a definition is answered before the seat list's reader started") } - if _, ok := follow(true).definition(seatlist.Seat)(); ok { + if _, ok := seatlist.Definition(follow(true).Reader, seatlist.Seat)(); ok { t.Error("a definition is answered while the seat mesh-catalog has not answered the list") } read := follow(false) - if d, ok := read.definition(seatlist.Seat)(); !ok || d.Seat != seatlist.Seat { + if d, ok := seatlist.Definition(read.Reader, seatlist.Seat)(); !ok || d.Seat != seatlist.Seat { t.Errorf("the read list's %s is answered as %q, %v", seatlist.Seat, d.Seat, ok) } - if _, ok := read.definition("no-such-seat")(); ok { + if _, ok := seatlist.Definition(read.Reader, "no-such-seat")(); ok { t.Error("a seat the list does not hold is answered a definition") } } diff --git a/modules/mesh-delivery-indexer/cmd/mesh-delivery-indexer/main.go b/modules/mesh-delivery-indexer/cmd/mesh-delivery-indexer/main.go index 8acd43e2..634ed0a9 100644 --- a/modules/mesh-delivery-indexer/cmd/mesh-delivery-indexer/main.go +++ b/modules/mesh-delivery-indexer/cmd/mesh-delivery-indexer/main.go @@ -39,6 +39,7 @@ import ( mcseat "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions" "git.novox.be/novox/mesh-sdk/go/process" "git.novox.be/novox/mesh-sdk/go/seatdef" + "git.novox.be/novox/mesh-sdk/go/seatlist" "git.novox.be/novox/mesh-sdk/go/views" "mesh-delivery-indexer/internal/index" @@ -450,7 +451,7 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro // connection, of any size (design 47 G §712, A-237). inputsStore := awaitedStore{b: process.AwaitBucket(ctx, js, conn, index.InputsBucket, "no input of a run ask is kept, so the verb input answers none", logger.Printf)} inObjects := &inputObjects{js: js, module: cred.Module} - stopInput, err := calls.AnswerSeat(meshcatalog.Seat, seatDefinition(seatReader, meshcatalog.Seat), map[string]process.SeatHandler{ + stopInput, err := calls.AnswerSeat(meshcatalog.Seat, seatlist.Definition(seatReader.Reader, meshcatalog.Seat), map[string]process.SeatHandler{ meshcatalog.VerbInput: index.InputVerb(inputsStore, inObjects, conn, buscalls.SeatAckWithin, logger.Printf)}) if err != nil { return fmt.Errorf("answering the verb input: %w", err) diff --git a/modules/mesh-delivery-indexer/cmd/mesh-delivery-indexer/seatlist.go b/modules/mesh-delivery-indexer/cmd/mesh-delivery-indexer/seatlist.go index 759a039b..8a2ebea9 100644 --- a/modules/mesh-delivery-indexer/cmd/mesh-delivery-indexer/seatlist.go +++ b/modules/mesh-delivery-indexer/cmd/mesh-delivery-indexer/seatlist.go @@ -10,7 +10,6 @@ import ( "github.com/nats-io/nats.go/jetstream" "git.novox.be/novox/mesh-sdk/go/process" - "git.novox.be/novox/mesh-sdk/go/seatdef" "git.novox.be/novox/mesh-sdk/go/seatlist" "git.novox.be/novox/mesh-sdk/go/views" @@ -142,17 +141,3 @@ func readWhenBound(part *seatlist.Part, states ...bucket) { // toolPrefix is the prefix of the indexer's tools, its manifest's slug. const toolPrefix = "indexer" - -// seatDefinition is the definition of seat the indexer's seat list holds, which the seat's verbs answered here check their -// callers against (process.Conn.AnswerSeat; design 47 G lead answers A-179, A-186): false until the list is read, so the -// indexer answers a verb only once its seat list is read, and false for a seat it does not hold. -func seatDefinition(part *seatlist.Part, seat string) func() (seatdef.Definition, bool) { - return func() (seatdef.Definition, bool) { - r := part.Reader() - if r == nil || !r.Status().Heard { - return seatdef.Definition{}, false - } - d, ok := r.Definitions()[seat] - return d, ok - } -} diff --git a/modules/mesh-delivery-indexer/cmd/mesh-delivery-indexer/seatlist_test.go b/modules/mesh-delivery-indexer/cmd/mesh-delivery-indexer/seatlist_test.go index e12a1dba..2637b9dc 100644 --- a/modules/mesh-delivery-indexer/cmd/mesh-delivery-indexer/seatlist_test.go +++ b/modules/mesh-delivery-indexer/cmd/mesh-delivery-indexer/seatlist_test.go @@ -51,10 +51,10 @@ func TestTheSeatListIsReadAgainWhenItsStatesAreBound(t *testing.T) { t.Fatal("the list was read with its states missing") } // A-179, A-186: the definition the verb input's callers are checked against is the list's once read, none before. - if _, ok := seatDefinition(seatlist.NewPart(toolPrefix, nil), seatlist.Seat)(); ok { + if _, ok := seatlist.Definition(seatlist.NewPart(toolPrefix, nil).Reader, seatlist.Seat)(); ok { t.Error("a definition is answered before the seat list's reader started") } - if _, ok := seatDefinition(part, seatlist.Seat)(); ok { + if _, ok := seatlist.Definition(part.Reader, seatlist.Seat)(); ok { t.Error("a definition is answered while the list is unread") } b := &awaitedFake{} @@ -70,10 +70,10 @@ func TestTheSeatListIsReadAgainWhenItsStatesAreBound(t *testing.T) { t.Fatal("the list was not read after its states were bound") } } - if d, ok := seatDefinition(part, seatlist.Seat)(); !ok || d.Seat != seatlist.Seat { + if d, ok := seatlist.Definition(part.Reader, seatlist.Seat)(); !ok || d.Seat != seatlist.Seat { t.Errorf("the read list's %s is answered as %q, %v", seatlist.Seat, d.Seat, ok) } - if _, ok := seatDefinition(part, "no-such-seat")(); ok { + if _, ok := seatlist.Definition(part.Reader, "no-such-seat")(); ok { t.Error("a seat the list does not hold is answered a definition") } var _ seatlist.Bus = bus diff --git a/modules/mesh-delivery-pipeline/cmd/mesh-delivery-pipeline/verbs.go b/modules/mesh-delivery-pipeline/cmd/mesh-delivery-pipeline/verbs.go index dbf008e0..4c62a4a7 100644 --- a/modules/mesh-delivery-pipeline/cmd/mesh-delivery-pipeline/verbs.go +++ b/modules/mesh-delivery-pipeline/cmd/mesh-delivery-pipeline/verbs.go @@ -12,7 +12,6 @@ import ( catalog "git.novox.be/novox/mesh-delivery/modules/mesh-delivery-contracts/go/seats/meshcatalog" seat "git.novox.be/novox/mesh-delivery/modules/mesh-delivery-contracts/go/seats/meshpipelinerunner" "git.novox.be/novox/mesh-sdk/go/process" - "git.novox.be/novox/mesh-sdk/go/seatdef" "git.novox.be/novox/mesh-sdk/go/seatlist" "mesh-delivery-pipeline/internal/pipeline" @@ -39,20 +38,7 @@ func verbOf[In any](do func(caller string, in In) (any, error)) process.SeatHand // G §22, §70, §306, §482, A-107), each call's caller checked against the seat's definition the runner's seat list holds // (A-179, A-186). The returned stop ends the answers. func answerVerbs(conn *process.Conn, seats *seatlist.Part, v pipeline.Verbs) (func(), error) { - return conn.AnswerSeat(seat.Seat, seatDefinition(seats, seat.Seat), writeHandlers(v)) -} - -// seatDefinition is the definition of seat the runner's seat list holds (A-186): false until the seat mesh-catalog has -// answered the list, so the runner answers a verb only once its seat list is read, and false for a seat it does not hold. -func seatDefinition(seats *seatlist.Part, name string) func() (seatdef.Definition, bool) { - return func() (seatdef.Definition, bool) { - r := seats.Reader() - if r == nil || !r.Status().Heard { - return seatdef.Definition{}, false - } - d, ok := r.Definitions()[name] - return d, ok - } + return conn.AnswerSeat(seat.Seat, seatlist.Definition(seats.Reader, seat.Seat), writeHandlers(v)) } // writeHandlers are the seat's write verbs the process answers: run, review, rerun, accept, cancel, start, ask-again and diff --git a/modules/mesh-delivery-pipeline/cmd/mesh-delivery-pipeline/verbs_test.go b/modules/mesh-delivery-pipeline/cmd/mesh-delivery-pipeline/verbs_test.go index 6368b5cd..d71a8898 100644 --- a/modules/mesh-delivery-pipeline/cmd/mesh-delivery-pipeline/verbs_test.go +++ b/modules/mesh-delivery-pipeline/cmd/mesh-delivery-pipeline/verbs_test.go @@ -70,17 +70,17 @@ func TestTheAnsweredSeatsDefinitionIsTheSeatListsOnceRead(t *testing.T) { } return p } - if _, ok := seatDefinition(seatlist.NewPart("runner", nil), seatlist.Seat)(); ok { + if _, ok := seatlist.Definition(seatlist.NewPart("runner", nil).Reader, seatlist.Seat)(); ok { t.Error("a definition is answered before the seat list's reader started") } - if _, ok := seatDefinition(follow(true), seatlist.Seat)(); ok { + if _, ok := seatlist.Definition(follow(true).Reader, seatlist.Seat)(); ok { t.Error("a definition is answered while the seat mesh-catalog has not answered the list") } read := follow(false) - if d, ok := seatDefinition(read, seatlist.Seat)(); !ok || d.Seat != seatlist.Seat { + if d, ok := seatlist.Definition(read.Reader, seatlist.Seat)(); !ok || d.Seat != seatlist.Seat { t.Errorf("the read list's %s is answered as %q, %v", seatlist.Seat, d.Seat, ok) } - if _, ok := seatDefinition(read, seat.Seat)(); ok { + if _, ok := seatlist.Definition(read.Reader, seat.Seat)(); ok { t.Error("a seat the list does not hold is answered a definition") } }