W16.6: the tool runner reads which modules exist and their manifests from the catalog half through meshcatalogclient's branch follower on its own consumer (milestone 47/G)

firstview adopts the shared branch follower over a wiring of its own consumer (views held with the assigner's, findings through its
held writer, events routed to each adopted view); the console's Source gives Modules from the catalog entries, the manifest an entry
carries whole; the indexer's modules and manifests first views and their consumes are removed, the registrations and the gate's
source-moved are consumed.

Builds: design 47 G §196, §594, §614; lead answers A-5, A-27, A-103

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
2026-11-11 23:40:23 +01:00
parent 4bfae38a73
commit 3501164f4b
9 changed files with 333 additions and 131 deletions
@@ -41,12 +41,12 @@ func TestTheRunnersConsumerCarriesTheOwnersViewsFamiliesWhenTheOwnersAreDownThen
if err := json.Unmarshal(raw, &manifest); err != nil {
t.Fatal(err)
}
streamOf := map[string]string{Assigner: catalogue.StreamBusName("assigner-views"), Indexer: catalogue.StreamBusName("indexer-views")}
streamOf := map[string]string{Assigner: catalogue.StreamBusName("assigner-views")}
filters := map[string][]string{}
families := 0
for _, c := range manifest.Consumes {
emitter, event, isView := strings.Cut(c, ".views.")
if !isView { // the seat mesh-catalog's events: the seat list's, on EVENTS (cmd/node-tools/seatlist.go)
if !isView { // the seats' events (the seat list's, the catalog half's), on EVENTS (cmd/node-tools/seatlist.go)
continue
}
stream := streamOf[emitter]
@@ -60,7 +60,7 @@ func TestTheRunnersConsumerCarriesTheOwnersViewsFamiliesWhenTheOwnersAreDownThen
t.Fatalf("the manifest consumes %d families, the runner holds %d first views", families, len(Specs))
}
runner := mt.MembershipOf("node-tools", "anchor", false, nil)
for _, owner := range []string{Assigner, Indexer} {
for _, owner := range []string{Assigner} {
stream := streamOf[owner]
mesh.ModuleStream(t, owner, stream)
mesh.ConsumerOn(t, stream, "anchor", "node-tools", filters[stream], 2*time.Second)
@@ -99,7 +99,7 @@ func TestTheRunnersConsumerCarriesTheOwnersViewsFamiliesWhenTheOwnersAreDownThen
mt.Until(t, func() error {
mu.Lock()
defer mu.Unlock()
if len(findings) != len(Specs) {
if len(findings) != len(Specs)+catalogViews {
return errFindings(len(findings))
}
return nil
@@ -130,7 +130,7 @@ func TestTheRunnersConsumerCarriesTheOwnersViewsFamiliesWhenTheOwnersAreDownThen
mt.Until(t, func() error {
mu.Lock()
defer mu.Unlock()
if len(findings) != 0 {
if len(findings) != catalogViews { // the seats' verbs are not served in this test: the catalog half stays unanswered
return errFindings(len(findings))
}
return nil
@@ -154,6 +154,10 @@ func TestTheRunnersConsumerCarriesTheOwnersViewsFamiliesWhenTheOwnersAreDownThen
}
}
// catalogViews is the first views the branch follower adopts before any branch is known: the registrations and the gate's source
// (design 47 G §614), each a finding while the seats' verbs go unanswered.
const catalogViews = 2
type errFindings int
func (e errFindings) Error() string { return "not yet" }