CAT-D4b, D5: the windows' driver moves the old-name and the direct-write windows on start, delivered and manifest-reads-changed

The windows' logic was built but nothing woke it, so both windows stayed open for ever. The program now reads every
node through node_haves and the node-engine seat's manifest-reads at its start, on each delivered and on each
manifest-reads-changed, steps both windows, says their closing once on distribution.events and raises the seven-day
finding. A build module's have counts as publishing through the seats when it runs a build heard publishing (the
tools bundle records the fingerprint of each publish's proved caller), so a paused build agent running the same
build holds nothing open.

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
2026-11-04 12:55:03 +01:00
parent 75986b2960
commit 99512eade4
7 changed files with 552 additions and 4 deletions
@@ -0,0 +1,190 @@
package holder
import (
"errors"
"fmt"
"slices"
"sort"
"strings"
"time"
)
// PublishingKey is the key of distribution's state windows that records, per build module, the fingerprints of the
// builds heard publishing through the seats: the tools bundle adds the have's fingerprint of the proved caller of each
// accepted publish. A node's have of a build module running one of them counts as publishing through the seats, so a
// node whose build module runs the same build but builds nothing (a paused build agent) does not hold the window.
const PublishingKey = "publishing"
// Publishing is that record: module -> fingerprints.
type Publishing struct {
Name string `json:"name"`
Modules map[string][]string `json:"modules"`
}
// Learn adds fp for module; it answers whether it was new.
func (p *Publishing) Learn(module, fp string) bool {
if module == "" || fp == "" {
return false
}
if p.Modules == nil {
p.Modules = map[string][]string{}
}
if slices.Contains(p.Modules[module], fp) {
return false
}
p.Modules[module] = append(p.Modules[module], fp)
sort.Strings(p.Modules[module])
return true
}
// NodeHave is one key of the status view's node_haves: a node, a module, the fingerprint it runs.
type NodeHave struct {
Node, Module, FP string
}
// Delivery is what the windows' driver asks of the delivery parts and the node-engine seat, through their tools and
// verbs on the bus (ADR 0596): every node's haves, away ones included, and one node-engine's stated reader
// capabilities. Reads answers served false when the node-engine does not serve `manifest-reads` (it states nothing).
type Delivery interface {
Haves() ([]NodeHave, error)
Reads(node string) (served bool, stated []string, err error)
}
// WindowState is distribution's state windows.
type WindowState interface {
Window(name string) (Window, error)
PutWindow(w Window) error
Publishing() (Publishing, error)
}
// Driver moves the old-name and the direct-write windows: at distribution's start, on each `delivered` and on each
// node-engine's `manifest-reads-changed` (ADR 0618 §4), never on a timer. Each wake reads every node, since a window
// closes only when no node holds it.
type Driver struct {
Delivery Delivery
State WindowState
Callers Callers
// Closed says a window's closing on distribution.events.
Closed func(c Closed) error
Finding func(kind, subject, words string, raised bool)
Now func() time.Time
}
// FindingWindowHeld is the finding of a node holding a window open for seven days.
const FindingWindowHeld = "window-held"
// Read reads every node: its haves, its node-engine's stated capabilities, and whether each build module's have runs a
// build heard publishing through the seats.
func (d *Driver) Read() ([]NodeRead, error) {
haves, err := d.Delivery.Haves()
if err != nil {
return nil, fmt.Errorf("node_haves cannot be read, so no window moves: %w", err)
}
pub, err := d.State.Publishing()
if err != nil {
return nil, fmt.Errorf("the publishing builds cannot be read, so no window moves: %w", err)
}
builds := d.Callers[VerbPublish]
byNode := map[string]*NodeRead{}
var order []string
for _, h := range haves {
if h.Module == "node" || h.Node == "" {
continue
}
n := byNode[h.Node]
if n == nil {
n = &NodeRead{Node: h.Node, NamesArtifact: true}
byNode[h.Node] = n
order = append(order, h.Node)
}
if slices.Contains(builds, h.Module) {
if n.BuildModules == nil {
n.BuildModules = map[string]bool{}
}
n.BuildModules[h.Module] = slices.Contains(pub.Modules[h.Module], h.FP)
}
}
sort.Strings(order)
out := make([]NodeRead, 0, len(order))
for _, node := range order {
n := byNode[node]
served, stated, err := d.Delivery.Reads(node)
if err != nil && served {
return nil, fmt.Errorf("%s's manifest-reads cannot be read, so no window moves: %w", node, err)
}
n.Serves, n.Stated = served, stated
out = append(out, *n)
}
return out, nil
}
// Wake reads every node and steps both windows; it answers a line for each thing it did, and an error when nothing
// could be judged.
func (d *Driver) Wake(why string) ([]string, error) {
nodes, err := d.Read()
if err != nil {
return nil, err
}
now := d.now()
var said, errs []string
for _, c := range []struct {
name, event, seat string
holding func([]NodeRead, []DroppedNode) []string
}{
{OldNameWindow, OldNameClosedEvent, OldSeat, HoldingOldName},
{DirectWritesWindow, DirectWritesClosedEvent, "", HoldingDirectWrites},
} {
cur, err := d.State.Window(c.name)
if err != nil {
errs = append(errs, err.Error())
continue
}
if cur.Name == "" {
cur = Window{Name: c.name, Open: true}
}
next, closed, overdue := cur.Step(c.holding(nodes, cur.Dropped), now)
if !windowsEqual(cur, next) {
if err := d.State.PutWindow(next); err != nil {
errs = append(errs, fmt.Sprintf("the %s window is not kept: %v", c.name, err))
continue
}
}
for _, n := range cur.Holding {
if !slices.Contains(overdue, n) && d.Finding != nil {
d.Finding(FindingWindowHeld, c.name+"."+n, "", false)
}
}
for _, n := range overdue {
if d.Finding != nil {
d.Finding(FindingWindowHeld, c.name+"."+n, fmt.Sprintf("%s has held distribution's %s window open since %s", n, c.name, next.Since[n].Format(time.RFC3339)), true)
}
}
if closed != nil {
closed.Seat = c.seat
if d.Closed != nil {
if err := d.Closed(*closed); err != nil {
errs = append(errs, fmt.Sprintf("%s was not said: %v", c.event, err))
}
}
said = append(said, fmt.Sprintf("the %s window is closed (%s); it was held last by %v", c.name, why, closed.LastHolding))
} else if next.Open {
said = append(said, fmt.Sprintf("the %s window stays open (%s): held by %v", c.name, why, next.Holding))
}
}
if len(errs) > 0 {
return said, errors.New(strings.Join(errs, "; "))
}
return said, nil
}
func (d *Driver) now() time.Time {
if d.Now != nil {
return d.Now()
}
return time.Now().UTC()
}
func windowsEqual(a, b Window) bool {
return a.Open == b.Open && slices.Equal(a.Holding, b.Holding) && a.Closed.Equal(b.Closed) &&
len(a.Since) == len(b.Since) && len(a.Dropped) == len(b.Dropped)
}
@@ -441,6 +441,42 @@ func TestTheHolderOfTheTwoImageSeats(t *testing.T) {
t.Error("a closed window closed again")
}
})
t.Run("the windows' driver: every node read on each wake, closed once, a paused build agent's same build counted", func(t *testing.T) {
del := &fakeDelivery{haves: []NodeHave{
{"ace", "mesh-build-go", "fp-new"}, {"novox", "mesh-build-go", "fp-new"}, {"g14", "mesh-build-go", "fp-old"},
{"g14", "node", ""}, {"ace", "gitea", "x"}, {"novox", "gitea", "x"},
}, stated: map[string][]string{"ace": {NewNamesCapability}, "novox": {NewNamesCapability}}}
st := &memWindows{w: map[string]Window{}}
st.pub.Learn("mesh-build-go", "fp-new")
var closed []string
found := map[string]bool{}
now := time.Unix(0, 0)
d := &Driver{Delivery: del, State: st, Callers: DefaultCallers(), Now: func() time.Time { return now },
Closed: func(c Closed) error { closed = append(closed, c.Window+" "+c.Seat); return nil },
Finding: func(kind, subject, _ string, raised bool) { found[kind+" "+subject] = raised }}
if _, err := d.Wake("start"); err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(st.w[OldNameWindow].Holding, []string{"g14"}) || !reflect.DeepEqual(st.w[DirectWritesWindow].Holding, []string{"g14"}) {
t.Errorf("windows = %+v, want g14 holding both (away: states nothing; runs the old build)", st.w)
}
now = now.Add(WindowFindingAfter)
_, _ = d.Wake("delivered")
if !found[FindingWindowHeld+" "+OldNameWindow+".g14"] {
t.Errorf("findings %v, want g14 named after seven days", found)
}
del.haves[2].FP, del.stated["g14"] = "fp-new", []string{NewNamesCapability}
if _, err := d.Wake("manifest-reads-changed on g14"); err != nil {
t.Fatal(err)
}
_, _ = d.Wake("delivered")
if want := []string{OldNameWindow + " " + OldSeat, DirectWritesWindow + " "}; !reflect.DeepEqual(closed, want) {
t.Errorf("closed %v, want each window said once, %v", closed, want)
}
if found[FindingWindowHeld+" "+OldNameWindow+".g14"] {
t.Error("the finding stays after the window closed")
}
})
t.Run("the manifest", func(t *testing.T) {
raw, err := os.ReadFile("../../module.json")
if err != nil {
@@ -85,3 +85,24 @@ func (f *fakeRegistry) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
}
}
// fakeDelivery answers the driver's reads: haves, and per node whether its node-engine serves manifest-reads.
type fakeDelivery struct {
haves []NodeHave
stated map[string][]string // a node absent does not serve manifest-reads
}
func (f *fakeDelivery) Haves() ([]NodeHave, error) { return f.haves, nil }
func (f *fakeDelivery) Reads(node string) (bool, []string, error) {
s, ok := f.stated[node]
return ok, s, nil
}
type memWindows struct {
w map[string]Window
pub Publishing
}
func (m *memWindows) Window(n string) (Window, error) { return m.w[n], nil }
func (m *memWindows) PutWindow(w Window) error { m.w[w.Name] = w; return nil }
func (m *memWindows) Publishing() (Publishing, error) { return m.pub, nil }