K-A2: mesh-config asks every proposal; the router holds the oldest back

Recovered from 71370afc (feat/47-G-asks).
Builds: design 47 G §40; design 46 §6 Limits, batching, history

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
2026-11-11 23:23:44 +01:00
parent 7df879b367
commit ff07c3a668
3 changed files with 6 additions and 9 deletions
+1 -1
View File
@@ -46,7 +46,7 @@ names who gave it in `by`, or on the operator's Approve of a proposal.
`action` `propose` (with `value`, or `clear`) judges the value as a set would, keeps it in `mesh-config_proposals`,
and asks the operator under mesh-config's own name on the `operator-channel` seat (its own grant, from `uses`, and
its own cap of three open asks; the same change twice is refused, and a newer proposal for the same level and key
the router holds an asker's oldest ask back behind a fourth, no cap of its own; the same change twice is refused, and a newer proposal for the same level and key
replaces the older). The ask says the level, the key and the value, exact where who answers is proven, and that,
approved, it takes effect at once on every node it reaches; Approve and Decline are both at the level approve and
each binds the proposal's level, key, value and the value it was shown against. On the answer mesh-config reads
@@ -641,8 +641,8 @@ func (c *Config) propose(call Call, action string) (Proposal, oc.Ask, []string,
return fail("the change carries %s, which leaves the mesh nowhere, so the operator could not be shown what "+
"they approve; config holds no secret, and %s", refusal, AtTheTerminalInstead)
}
// **Its own cap of open asks, and the same change once** (ADR 0277 §21); a newer proposal for the same place
// replaces an older one still open (§10).
// **The same change once** (ADR 0277 §21); a newer proposal for the same place replaces an older one still open
// (§10). No cap of open asks of its own: the router offers at most three and holds the oldest back (ADR 0666 §12).
all, err := c.proposals()
if err != nil {
return Proposal{}, oc.Ask{}, nil, err
@@ -662,10 +662,6 @@ func (c *Config) propose(call Call, action string) (Proposal, oc.Ask, []string,
}
open++
}
if open >= occ.MostOpen {
return fail("%d proposals already wait for the operator's answer, and mesh-config asks at most %d at once; "+
"config's proposals lists them", open, occ.MostOpen)
}
if why := approverReady(c.Asks); why != "" {
return fail("%s; %s", why, AtTheTerminalInstead)
}
@@ -484,9 +484,10 @@ func TestAProposalIsJudgedAndRefusedBeforeTheOperatorIsAsked(t *testing.T) {
}
propose(t, c, Call{Key: "font-size", Value: 15.0, Node: "novox"})
propose(t, c, Call{Key: "agent-managed-settings", Value: map[string]any{"a": 1.0}})
// A fourth is asked, never refused: the router holds the asker's oldest back (ADR 0666 §12).
if _, err := c.Propose(Call{Action: "propose", Key: "width", Value: 400.0, Node: "g14", Module: "dunst",
Caller: "g", Why: "w"}); err == nil || !strings.Contains(err.Error(), "3 proposals already wait") {
t.Errorf("a fourth open ask: %v", err)
Caller: "g", Why: "w"}); err != nil {
t.Errorf("a fourth open ask was refused: %v", err)
}
if keys, _ := m.Keys(ValuesState); len(keys) != 1 {
t.Errorf("proposals set %v", keys)