From 206f794eb319136a93cfaac57e5f18bee0a1ce8b Mon Sep 17 00:00:00 2001 From: jochen Date: Fri, 30 Oct 2026 18:35:54 +0100 Subject: [PATCH] Grant a bar's holder the state a contributor's item shows, at its own machine's key (issue 774) i3status-rust on g14 and shanks was issued nothing to read ("was issued: none", 148 times): ReadsGranted derived a holder's reads from contributions' data alone, and design 57 L3 moved power's draw block to an item (mesh-catalog ca8d6f33: shows: state, state: power.draw). ReadsGranted now reads a module's items of a kind the holder's seat receives too, their attributes in a contribution's data shape, always at the machine's own key (ADR 0260), never another's. Both callers, the controller's busrecords and mesh-grants' records.go, get it through ReadsGranted with no change of their own. --- go/catalogue/seat_data.go | 30 +++++++++++++++++++++++++++++- go/catalogue/seat_data_test.go | 10 ++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/go/catalogue/seat_data.go b/go/catalogue/seat_data.go index 90a1fb7..ab3bbcf 100644 --- a/go/catalogue/seat_data.go +++ b/go/catalogue/seat_data.go @@ -155,7 +155,9 @@ var stateKeyName = regexp.MustCompile(`^[a-z0-9][a-z0-9-]*$`) // ReadsGranted is the state a holder reads because modules on its machine offer it in pieces of a // kind its seat receives as data (novox/hq ADR 0260), each with the one key the piece shows — the -// machine's own when it names none — sorted and once each. The bus grants the holder these keys and +// machine's own when it names none — sorted and once each. A module's items of such a kind (design 57 L3) grant +// what they show too, always at the machine's own key; an item whose capability the machine lacks grants a key +// that is never written, which is no wider than its own machine's. The bus grants the holder these keys and // no others: the holder names no contributor, and reads only what is offered to it where it runs. func ReadsGranted(holder Manifest, onMachine []Manifest, machine string) []StateRead { seen := map[StateRead]bool{} @@ -183,6 +185,21 @@ func ReadsGranted(holder Manifest, onMachine []Manifest, machine string) []State } } } + // A moved contributor's items of the kind (design 57 L3): what each shows, read from its attributes as a + // contribution's data, and always this machine's own key (ADR 0260), never another's (issue 774: + // power's draw block became an item and i3status-rust was issued nothing). + for _, it := range m.Items { + if it.Collection != "contribution:"+s.Name+":"+r.Kind { + continue + } + for _, sr := range r.Shape.Reads(itemData(it)) { + sr.Key = machine + if module, _, err := ReadState(sr.Read); err == nil && module == m.Module && module != holder.Module && + stateKeyName.MatchString(sr.Key) { + seen[sr] = true + } + } + } } } } @@ -199,6 +216,17 @@ func ReadsGranted(holder Manifest, onMachine []Manifest, machine string) []State return out } +// itemData is an item's attributes in the shape of a contribution's data: each at the top and among the options, where +// a shape's Reads looks for what a piece shows (barBlockReads: shows, options.state). +func itemData(it Item) map[string]any { + data, options := map[string]any{}, map[string]any{} + for k, v := range it.Attributes { + data[k], options[k] = v, v + } + data["options"] = options + return data +} + // wholeIn is v as a whole number within [lo, hi]; JSON gives every number as a float. func wholeIn(v any, lo, hi int) (int, bool) { f, ok := v.(float64) diff --git a/go/catalogue/seat_data_test.go b/go/catalogue/seat_data_test.go index 3d2313e..d39c59e 100644 --- a/go/catalogue/seat_data_test.go +++ b/go/catalogue/seat_data_test.go @@ -394,6 +394,16 @@ func TestAStateBlockIsRenderedForThisMachineAndTheHolderIsGrantedToReadIt(t *tes if got := ReadsGranted(barHolder(), []Manifest{barHolder()}, "laptop"); len(got) != 0 { t.Fatalf("a holder alone is granted %v", got) } + // Issue 774 (design 57 L3): the block as an item grants the same read, at this machine's own key alone, even where + // the item names another machine's. + for _, attrs := range []map[string]string{{"shows": "state", "state": "power.draw"}, {"shows": "state", "state": "power.draw", "key": "other"}} { + moved := Manifest{Module: "power", State: []StateDeclaration{{Name: "draw"}}, Items: []Item{{ + Collection: "contribution:node-bar:block", Name: "power-draw", IfCapability: "power-meter", Attributes: attrs}}} + if got := ReadsGranted(barHolder(), []Manifest{barHolder(), moved}, "laptop"); len(got) != 1 || + got[0] != (StateRead{Read: "power.draw", Key: "laptop"}) { + t.Errorf("the holder is granted %v by the item %v", got, attrs) + } + } } func TestAModuleOffersItsOwnStateOnly(t *testing.T) {