A-372 assigner-settles-on-a-mesh-naming-no-branch: the assigner's first pass is told once when the catalog client says the registrations and the source name no branch

Builds: design 47 G A-372 (G-22-lead-answers-2.md, hq design/47-G-lead-answers-31)
Also: Ready reads what the first views hold, since a first view closes before the follower's change is taken into the branches followed; Branches.FirstViews says when both are in.

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
2026-11-13 20:57:52 +01:00
parent 27072735e9
commit e383004afc
@@ -51,9 +51,39 @@ func (h *halves) follow() error {
h.mu.Lock()
h.branches = b
h.mu.Unlock()
h.settleWhenNoBranch()
return nil
}
// settleWhenNoBranch tells the first pass once, when the registrations and the gate's source are answered and name no branch: the
// trunk is none-yet and the world is empty, as the catalog client's Ready says it (design 47 G, A-372). A mesh that names a branch is
// told by adopted, when that branch's first view is answered.
func (h *halves) settleWhenNoBranch() {
if h.settled == nil {
return
}
h.mu.Lock()
b := h.branches
h.mu.Unlock()
go func() {
select {
case <-b.FirstViews(h.ctx):
case <-h.ctx.Done():
return
}
if len(b.Followed()) > 0 || b.Ready() != nil {
return
}
h.mu.Lock()
told := h.told
h.told = true
h.mu.Unlock()
if !told {
h.settled <- struct{}{}
}
}()
}
// first is the first watched branch followed, the trunk's: "" while none is.
func (h *halves) first() string {
h.mu.Lock()