From 2e8c2a7f4c67223e8b3ca0cc1544014385627091 Mon Sep 17 00:00:00 2001 From: jochen Date: Tue, 27 Oct 2026 22:49:06 +0100 Subject: [PATCH 1/3] =?UTF-8?q?Seat=20mesh-delivery-checker:=20the=20try?= =?UTF-8?q?=20and=20its=20read=20are=20verbs=20of=20the=20checker's=20own?= =?UTF-8?q?=20seat,=20replacing=20sh=20merge-check.sh=20(ADR=200547=20?= =?UTF-8?q?=C2=A710,=20issue=20774)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go/catalogue/checker_seat.go | 32 +++++++++++++++++++++++++++++++ go/catalogue/checker_seat_test.go | 29 ++++++++++++++++++++++++++++ go/catalogue/seats.go | 2 ++ go/catalogue/seats_test.go | 5 +++-- 4 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 go/catalogue/checker_seat.go create mode 100644 go/catalogue/checker_seat_test.go diff --git a/go/catalogue/checker_seat.go b/go/catalogue/checker_seat.go new file mode 100644 index 0000000..30e8468 --- /dev/null +++ b/go/catalogue/checker_seat.go @@ -0,0 +1,32 @@ +package catalogue + +// The delivery's checker (novox/hq ADR 0547 §10, issue 774): one holder for the mesh, the module +// mesh-delivery-checker, which judges a pull request's head and a pushed head the same way. The try the +// controller forwarded to it is a verb of this seat, answered by the checker with the verdict it gives a pull +// request, so the try outlives the controller. + +// CheckerSeat is the seat mesh-delivery-checker holds. +const CheckerSeat = "mesh-delivery-checker" + +// checkerVerbs are the checker seat's verbs: ask a try, read one. Optional until the checker serves them +// everywhere. +func checkerVerbs() []Verb { + return []Verb{ + {Name: "try", Optional: true, Description: "Try a pushed head before its pull request is opened: the checker " + + "judges it as it judges a pull request's head, merged onto its trunk's head, its unit and integration " + + "levels through the build modules, and owes the forge nothing. Answers the try's id at once; try-read " + + "reads where it stands. A try of the same head that waits or runs is the answer to a second ask; at most " + + "4 wait or run at once, mesh-wide.", + Input: schema(map[string]string{"repository": "/", + "head": "the full commit to try, 40 or 64 hex digits", + "trunk": "the trunk commit to merge it onto, or the trunk's branch for its head now; the trunk's head when absent", + "tests": "a go test -run pattern: only those tests run, and nothing is kept", + "level": "unit or integration: only this level; both when absent"}, + []string{"repository", "head"}), + Replaces: []string{"sh merge-check.sh"}}, + {Name: "try-read", Optional: true, Description: "Where a try stands, as stored: queued, running, or its end " + + "(pass, fail, or error when it could not run), with what was said of it, the head and the trunk commit " + + "it was merged onto, the time it took and what failed first. Read-only.", + Input: schema(map[string]string{"id": "the try's id, try-"}, []string{"id"})}, + } +} diff --git a/go/catalogue/checker_seat_test.go b/go/catalogue/checker_seat_test.go new file mode 100644 index 0000000..f714337 --- /dev/null +++ b/go/catalogue/checker_seat_test.go @@ -0,0 +1,29 @@ +package catalogue + +import ( + "slices" + "testing" +) + +// The try is a verb of the checker's seat and carries the shell command it replaces (ADR 0547 §10, ADR 0245). +func TestTheCheckerSeatServesTheTry(t *testing.T) { + var seat *Seat + for _, s := range defaultSeats { + if s.Name == CheckerSeat { + seat = &s + } + } + if seat == nil || seat.Scope != ScopeMesh { + t.Fatalf("seat = %+v", seat) + } + var names []string + for _, v := range seat.Serves { + names = append(names, v.Name) + if v.Name == "try" && !slices.Equal(v.Replaces, []string{"sh merge-check.sh"}) { + t.Errorf("try replaces %v", v.Replaces) + } + } + if !slices.Equal(names, []string{"try", "try-read"}) { + t.Errorf("verbs = %v", names) + } +} diff --git a/go/catalogue/seats.go b/go/catalogue/seats.go index 312c3b0..f47ba62 100644 --- a/go/catalogue/seats.go +++ b/go/catalogue/seats.go @@ -258,6 +258,8 @@ var defaultSeats = append([]Seat{ // machine, and a group of them, recorded and ordered by its holder, which asks the controller for each act. // What it says it says as its module (`mesh-delivery.transition`), through the runtime that launches it. {Name: DeliverySeat, Scope: ScopeMesh, Serves: deliveryVerbs(), Decision: "novox/hq ADR 0239"}, + // The delivery's checker (novox/hq ADR 0547 §10, issue 774): the try is its verb, not the controller's. + {Name: CheckerSeat, Scope: ScopeMesh, Serves: checkerVerbs(), Decision: "novox/hq ADR 0547"}, // Deferred renames (novox/hq ADR 0121): these deliver a provision, so renaming them is a // delivering-seat migration with a mesh-wide cascade if a holder stops resolving mid-flight. // They keep their names until that migration is done deliberately, apart from the node-* pass. diff --git a/go/catalogue/seats_test.go b/go/catalogue/seats_test.go index 62043e1..7b4a23a 100644 --- a/go/catalogue/seats_test.go +++ b/go/catalogue/seats_test.go @@ -56,8 +56,9 @@ func TestTheSeatsAreAClosedSetAndEachNamesItsDecision(t *testing.T) { // node-container-runtime (ADR 0207); nineteen with node-environment and node-login-shell (ADR 0203, // ADR 0204); seventeen with node-build-agent (ADR 0190). One fewer once the retired // mesh-build-machine row goes, when no registered manifest claims it. - if len(Seats()) != 46 { - t.Errorf("the mesh defines %d seats rather than 46; the set is closed, so a change here is "+ + // Forty-seven with mesh-delivery-checker (novox/hq ADR 0547 §10, issue 774). + if len(Seats()) != 47 { + t.Errorf("the mesh defines %d seats rather than 47; the set is closed, so a change here is "+ "a decision (novox/hq ADR 0110): %s", len(Seats()), seatNames()) } } From 9fdd33b03edccc393f7dbb011e486b8275512256 Mon Sep 17 00:00:00 2001 From: jochen Date: Tue, 27 Oct 2026 22:49:44 +0100 Subject: [PATCH 2/3] Checker seat: the try's end by hand is a verb too (issue 774) --- go/catalogue/checker_seat.go | 7 ++++++- go/catalogue/checker_seat_test.go | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/go/catalogue/checker_seat.go b/go/catalogue/checker_seat.go index 30e8468..7426d2c 100644 --- a/go/catalogue/checker_seat.go +++ b/go/catalogue/checker_seat.go @@ -8,7 +8,7 @@ package catalogue // CheckerSeat is the seat mesh-delivery-checker holds. const CheckerSeat = "mesh-delivery-checker" -// checkerVerbs are the checker seat's verbs: ask a try, read one. Optional until the checker serves them +// checkerVerbs are the checker seat's verbs: ask a try, read one, end one by hand. Optional until the checker serves them // everywhere. func checkerVerbs() []Verb { return []Verb{ @@ -28,5 +28,10 @@ func checkerVerbs() []Verb { "(pass, fail, or error when it could not run), with what was said of it, the head and the trunk commit " + "it was merged onto, the time it took and what failed first. Read-only.", Input: schema(map[string]string{"id": "the try's id, try-"}, []string{"id"})}, + {Name: "try-end", Optional: true, Description: "End a try that waits or runs, as error, by hand: say why (kept in " + + "what it says). Its place among the tries is free at once and the next try of its head asks anew with a new " + + "id. A try that ended already is refused.", + Input: schema(map[string]string{"id": "the try's id, try-", "why": "why it is ended, in words"}, + []string{"id", "why"})}, } } diff --git a/go/catalogue/checker_seat_test.go b/go/catalogue/checker_seat_test.go index f714337..784bf71 100644 --- a/go/catalogue/checker_seat_test.go +++ b/go/catalogue/checker_seat_test.go @@ -23,7 +23,7 @@ func TestTheCheckerSeatServesTheTry(t *testing.T) { t.Errorf("try replaces %v", v.Replaces) } } - if !slices.Equal(names, []string{"try", "try-read"}) { + if !slices.Equal(names, []string{"try", "try-read", "try-end"}) { t.Errorf("verbs = %v", names) } } From a5d0e6420060f6a67cacd5247bd7c37b08840e1e Mon Sep 17 00:00:00 2001 From: jochen Date: Tue, 27 Oct 2026 23:00:38 +0100 Subject: [PATCH 3/3] Checker seat test: fold into the closed-set seats test, no new test function (issue 774) --- go/catalogue/checker_seat_test.go | 29 ----------------------------- go/catalogue/seats_test.go | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 29 deletions(-) delete mode 100644 go/catalogue/checker_seat_test.go diff --git a/go/catalogue/checker_seat_test.go b/go/catalogue/checker_seat_test.go deleted file mode 100644 index 784bf71..0000000 --- a/go/catalogue/checker_seat_test.go +++ /dev/null @@ -1,29 +0,0 @@ -package catalogue - -import ( - "slices" - "testing" -) - -// The try is a verb of the checker's seat and carries the shell command it replaces (ADR 0547 §10, ADR 0245). -func TestTheCheckerSeatServesTheTry(t *testing.T) { - var seat *Seat - for _, s := range defaultSeats { - if s.Name == CheckerSeat { - seat = &s - } - } - if seat == nil || seat.Scope != ScopeMesh { - t.Fatalf("seat = %+v", seat) - } - var names []string - for _, v := range seat.Serves { - names = append(names, v.Name) - if v.Name == "try" && !slices.Equal(v.Replaces, []string{"sh merge-check.sh"}) { - t.Errorf("try replaces %v", v.Replaces) - } - } - if !slices.Equal(names, []string{"try", "try-read", "try-end"}) { - t.Errorf("verbs = %v", names) - } -} diff --git a/go/catalogue/seats_test.go b/go/catalogue/seats_test.go index 7b4a23a..137cc98 100644 --- a/go/catalogue/seats_test.go +++ b/go/catalogue/seats_test.go @@ -43,6 +43,21 @@ func TestTheSeatsAreAClosedSetAndEachNamesItsDecision(t *testing.T) { delivered[s.Delivers] = s.Name } } + // The checker's seat serves the try, which replaces the shell's merge check (ADR 0547 §10, ADR 0245). + var checkerVerbs []string + for _, s := range Seats() { + if s.Name == CheckerSeat { + for _, v := range s.Serves { + checkerVerbs = append(checkerVerbs, v.Name) + if v.Name == "try" && strings.Join(v.Replaces, "|") != "sh merge-check.sh" { + t.Errorf("try replaces %v", v.Replaces) + } + } + } + } + if strings.Join(checkerVerbs, ",") != "try,try-read,try-end" { + t.Errorf("the checker seat serves %v", checkerVerbs) + } // Forty-six with the three build seats replacing node-build-agent and the retired mesh-build-machine (novox/hq // ADR 0525 §2, §10); forty-five with node-files (novox/hq ADR 0394); forty-four again once node-reads goes. // Forty-four with node-provisioner (novox/hq ADR 0349 clause 3); forty-three with mesh-provisioner (novox/hq ADR 0349 clause 3); forty-two with mesh-config (novox/hq ADR 0348 §9); forty-one with node-reads (novox/hq ADR 0310); forty with node-nfs-server and node-mounts (novox/hq ADR 0263); thirty-eight with node-resolver (novox/hq ADR 0247); thirty-seven with mesh-delivery (novox/hq ADR 0239); thirty-six since node-resolver-config retired