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
This commit is contained in:
2026-11-12 11:39:57 +01:00
parent 7c461a96ae
commit db3f07d277
11 changed files with 21 additions and 80 deletions
@@ -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)
}
@@ -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>.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
}
}
@@ -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")
}
}
@@ -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)
@@ -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
}
}
@@ -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")
}
}
@@ -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)
@@ -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
}
}
@@ -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
@@ -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
@@ -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")
}
}