view_tiers names bus state by the assigner's held want alone, never by a provisioner key no one makes (ADR 0614 §5; issue 774)

bus-state is offered with no credential of a consumer's own, so the provisioner keys nothing for it; the view showed
every module asking bus state as waiting for that key for good.

Claude-Session: https://claude.ai/code/session_01JG73KG7AfSdh6FP8VrBqCn
This commit is contained in:
2026-11-03 23:42:37 +01:00
parent 9d2816d001
commit 2d49c660c0
2 changed files with 12 additions and 9 deletions
@@ -107,8 +107,9 @@ func tiersToolSaysEachModulesWait(t *testing.T) {
if out, err := run(t, r, view.TiersTool, map[string]any{}); err != nil || out.(view.Tiers).Revision != 9 || out.(view.Tiers).Modules != 3 {
t.Errorf("view_tiers of the gate's newest = %+v, %v", out, err)
}
// ADR 0614 §2-§5: a want held on a verb or a reader capability is named by its edge, a wait for bus state as bus state,
// and each verb edge the graph leaves out on a cycle is named.
// ADR 0614 §2-§5: a want held on a verb, a reader capability or bus state is named by its edge; bus state is no
// provisioner key (none is ever made for it), so a module asking it shows no provision wait of it; and each verb edge
// the graph leaves out on a cycle is named.
r.GraphState = fake{
"db": node(graph.Node{FP: fp("a"), Repository: "novox/mesh-catalog", Provides: []string{"database"}}),
"web": node(graph.Node{FP: fp("b"), Repository: "novox/mesh-catalog", Requires: []string{"database", graph.BusState}, Awaits: []string{"database", graph.BusState},
@@ -127,9 +128,9 @@ func tiersToolSaysEachModulesWait(t *testing.T) {
t.Fatalf("view_tiers 9 = %+v, %v", out, err)
}
web := got.Tiers[1][0]
if len(web.Waits) != 3 || web.Waits[0].Edge != edge || web.Waits[1].Edge != "bus state" || !strings.Contains(web.Waits[1].Words, "no key of bus-state") ||
if len(web.Waits) != 2 || web.Waits[0].Edge != edge || web.Waits[1].Edge != "provision database" ||
!reflect.DeepEqual(web.LeftOut, []string{"db.loop"}) {
t.Errorf("web held by %q = %+v, want its want named %s, a bus state wait and db.loop left out", words, web, edge)
t.Errorf("web held by %q = %+v, want its want named %s, no wait for a bus-state key and db.loop left out", words, web, edge)
}
}
// The graph not readable: every module in the first tier, said; past 500 modules the answer says it is cut short.
@@ -57,8 +57,8 @@ type TierModule struct {
LeftOut []string `json:"left-out,omitempty"`
}
// TierWait is one thing a module waits on: the edge (build, have, provision <name>, bus state, or for a want held back
// want, verb <verb> or reader capability <capabilities> as the assigner's words name it, ADR 0614 §2, §4, §5), the node
// TierWait is one thing a module waits on: the edge (build, have, provision <name>, or for a want held back want, verb
// <verb>, reader capability <capabilities> or bus state as the assigner's words name it, ADR 0614 §2, §4, §5), the node
// it waits on (none for its build), the assigner's rule for a want held back, the part's words and since when, where the
// part says it.
type TierWait struct {
@@ -249,6 +249,11 @@ func (r Reader) waitsOf(module string, m delivery.Module, g graph.Node, wants, p
out = append(out, hw)
}
for _, a := range g.Awaits {
if a == graph.BusState {
// Bus state is offered with no credential of a consumer's own, so the provisioner keys nothing for it: its wait is
// the assigner's held want alone, named bus state from its words (ADR 0614 §5).
continue
}
out = append(out, provisionWaits(node, module, a, provided, perr)...)
}
}
@@ -323,9 +328,6 @@ func (r Reader) haveWait(node, module, fp string) (TierWait, bool) {
// provisionWaits are the waits of the provision a that module awaits on node: none once every key of it is provided.
func provisionWaits(node, module, a string, provided map[string]json.RawMessage, perr error) []TierWait {
edge := "provision " + a
if a == graph.BusState {
edge = "bus state" // a bus-state entry of the manifest (ADR 0614 §5)
}
if perr != nil {
return []TierWait{{Edge: edge, Node: node, Words: "the provisioner's keys cannot be read: " + perr.Error()}}
}