Make the catalogue test strict: the gate alone claims the seat, and say the old module is gone (ADR 0454, issue 1351)
mesh/merge-gate head 1c7024224dd7 merged into trunk bb0fe93bbddd — pass: builds mesh-delivery, mesh-issues → novox; no bus step; every machine composes wit…
mesh/repo-check head 1c7024224dd7 merged into trunk bb0fe93bbddd — pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-…
mesh/delivery delivered

This commit is contained in:
2026-10-20 12:03:46 +00:00
parent 1ef19030f1
commit 1c7024224d
5 changed files with 24 additions and 26 deletions
-2
View File
@@ -8,13 +8,11 @@ modules/messenger/cmd/messenger/messenger
modules/mesh-watcher/cmd/mesh-watcher/mesh-watcher
modules/claude-code/cmd/claude-code/claude-code
modules/dnsmasq/cmd/dnsmasq-tools/dnsmasq-tools
modules/mesh-delivery/cmd/mesh-delivery/mesh-delivery
# ...and the same built from the module's root (go build ./cmd/<name>), which names it after the module.
modules/messenger/messenger
modules/claude-code/claude-code
modules/mesh-watcher/mesh-watcher
modules/dnsmasq/dnsmasq
modules/mesh-delivery/mesh-delivery
modules/mesh-issues/cmd/mesh-issues/mesh-issues
modules/mounts/cmd/mounts/mounts
modules/mesh-knowledge/cmd/mesh-knowledge/mesh-knowledge
+7 -7
View File
@@ -22,9 +22,9 @@ ends as covered or delivered when a later merge covers it.
## Taking the seat over from today's module
The gate claims the seat `mesh-delivery` beside the module `mesh-delivery`, which the catalogue still holds, unchanged. The
controller refuses a merge that removes a module that is assigned, so today's module stays in the catalogue until it is
unassigned, and goes by a handover of verbs after the merge, never by hand on a machine (novox/hq ADR 0449 §4, ADR 0450 §6):
The gate claims the seat `mesh-delivery` and took it over from the module `mesh-delivery`, which the catalogue no longer holds.
The controller refuses a merge that removes a module that is assigned, so today's module stayed in the catalogue until it was
unassigned, and went by a handover of verbs after the merge, never by hand on a machine (novox/hq ADR 0449 §4, ADR 0450 §6, ADR 0454):
1. assign `mesh-delivery-gate` to the machine that holds the seat (`mesh-controller.assign`);
2. check that `mesh-controller.seats` still names `mesh-delivery`, held by the running module;
@@ -36,7 +36,7 @@ unassigned, and goes by a handover of verbs after the merge, never by hand on a
Until then the gate is silent: it takes no event, writes no key, asks nothing and answers no verb but `delivery_status`, which
says why (`holds-the-seat`, `seat-waits`).
After the handover, the removal of `modules/mesh-delivery` follows as a pull request of its own, merged by the gate; the catalogue
then has one claimant of the seat. Until then the catalogue holds exactly these two, and the names of the old module that
the handover needs, and no others: the three buckets the gate carries
over, and the event the issue tracker and the tool runner hear until the module is forgotten (`catalogue_test.go`).
The removal of `modules/mesh-delivery` followed the handover as a pull request of its own, merged by the gate (ADR 0454); the
catalogue has one claimant of the seat, and no manifest but the gate's and the issue tracker's names the old module but the names
the handover needed: the three buckets the gate carries over, and the event the issue tracker and the tool runner hear
(`catalogue_test.go`).
@@ -9,24 +9,20 @@ import (
"testing"
)
// **The gate and today's module are the two claimants of the seat in the catalogue** (novox/hq ADR 0437 §1, ADR 0449 §4, issue
// 1351; how it is checked). R3e keeps `modules/mesh-delivery` unchanged: the controller refuses a merge that removes a module
// still assigned, and today's module is assigned until the handover, which follows the merge. Its removal is a pull request of
// its own after the handover, which makes the claimants exactly one. Until then exactly these two claim the seat `mesh-delivery`
// and no third does (the seat's pass counts only assigned claimants, mesh-controller internal/catalogue/seat_pass.go
// SeatsToPassOn, so the unassigned one does not block it). And no manifest but the gate's and mesh-issues' names today's module
// in what it reads or hears, but through the seat's name (`mesh-delivery` as a seat or a repository, `seat:mesh-delivery.<verb>`)
// and the names below, which stay until today's module is forgotten: the three buckets the gate carries over (ADR 0450 §6) and
// the event the trackers hear (issue 1350). Today's module itself is left out: it is unchanged.
// **The gate is the only claimant of the seat `mesh-delivery` in the catalogue** (novox/hq ADR 0437 §1, ADR 0449 §4, ADR 0454,
// issue 1351; how it is checked). Today's module `modules/mesh-delivery` was removed by a pull request of its own after the
// handover, so the claimants are exactly one. And no manifest but the gate's and mesh-issues' names the old module in what it
// reads or hears, but through the seat's name (`mesh-delivery` as a seat or a repository, `seat:mesh-delivery.<verb>`) and the
// names below: the three buckets the gate carries over (ADR 0450 §6) and the event the trackers hear (issue 1350).
var oldModuleNames = map[string][]string{
"mesh-delivery-gate": {"mesh-delivery.deliveries", "mesh-delivery.groups", "mesh-delivery.pulls"},
"mesh-issues": {"mesh-delivery.transition"},
}
// seatClaimants are the modules that claim the seat: the gate, and today's module until its removal.
var seatClaimants = []string{"mesh-delivery", "mesh-delivery-gate"}
// seatClaimants are the modules that claim the seat: the gate alone.
var seatClaimants = []string{"mesh-delivery-gate"}
func TestTheCatalogueHoldsTheGateAndTodaysModuleAsTheOnlyClaimantsOfTheSeat(t *testing.T) {
func TestTheCatalogueHoldsTheGateAsTheOnlyClaimantOfTheSeat(t *testing.T) {
modules := filepath.Join("..", "..", "..")
dirs, err := os.ReadDir(modules)
if err != nil {
@@ -54,9 +50,6 @@ func TestTheCatalogueHoldsTheGateAndTodaysModuleAsTheOnlyClaimantsOfTheSeat(t *t
claimants = append(claimants, manifest.Module)
}
}
if dir.Name() == "mesh-delivery" {
continue // today's module, unchanged: it names itself
}
var generic any
_ = json.Unmarshal(raw, &generic)
var walk func(v any)
@@ -80,7 +73,7 @@ func TestTheCatalogueHoldsTheGateAndTodaysModuleAsTheOnlyClaimantsOfTheSeat(t *t
}
slices.Sort(claimants)
if !slices.Equal(claimants, seatClaimants) {
t.Errorf("the seat mesh-delivery is claimed by %v; wanted exactly %v (the removal of today's module makes it one)", claimants, seatClaimants)
t.Errorf("the seat mesh-delivery is claimed by %v; wanted exactly %v (today's module is removed)", claimants, seatClaimants)
}
if read < 20 {
t.Fatalf("only %d manifests were read: the catalogue is not where the test looks", read)
+1 -1
View File
@@ -222,7 +222,7 @@ var LinkKinds = []string{LinkDuplicates, LinkRelatesTo, LinkDependsOn, LinkPullR
var (
pullRequest = regexp.MustCompile(`^[a-z0-9][a-z0-9._-]{0,99}#[1-9][0-9]{0,6}$`)
decision = regexp.MustCompile(`^[0-9]{4}$`)
// deliveryID mirrors mesh-delivery's `IDOf` (modules/mesh-delivery/cmd/mesh-delivery/model.go): the forge's
// deliveryID mirrors the delivery gate's `IDOf` (modules/mesh-delivery-gate/cmd/mesh-delivery-gate/model.go): the forge's
// repository as owner/name, lower-cased, `@` and at most twelve characters of its commit. The pattern this
// replaced took neither the slash nor the `@`, so no delivery could be linked (novox/hq issue 475).
deliveryID = regexp.MustCompile(`^[a-z0-9][a-z0-9._-]{0,99}/[a-z0-9][a-z0-9._-]{0,99}@[0-9a-f]{1,12}$`)
@@ -5,6 +5,7 @@ import (
"os"
"path/filepath"
"reflect"
"slices"
"sort"
"strings"
"testing"
@@ -171,7 +172,13 @@ func TestTheSettingsStartTheCounterAndRegisterTheOwners(t *testing.T) {
}
}
modules := filepath.Join("..", "..", "..")
// retired are modules the catalogue no longer holds that stay registered, because issues are located in them
// (novox/hq ADR 0454, issue 1351: today's delivery module, removed after the gate took the seat).
retired := []string{"mesh-catalog modules/mesh-delivery"}
for _, o := range s.Owners {
if slices.Contains(retired, o) {
continue
}
if name, ok := strings.CutPrefix(o, "mesh-catalog modules/"); ok {
if _, err := os.Stat(filepath.Join(modules, name, "module.json")); err != nil {
t.Errorf("the owner %q names a module the catalogue does not hold", o)