Say the router's refusal of a proposal only once its discard is kept (issue 589)
mesh/merge-gate head e4e0ce761901 merged into trunk 9c9a76d220f8 — pass: builds claude-code → ace, g14, novox, shanks; no bus step; every machine composes …
mesh/repo-check head e4e0ce761901 merged into trunk 9c9a76d220f8 — pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-…
mesh/delivery superseded: a newer head of the same pull request

The refusal test failed on a loaded build agent: Propose returned on hearing the
refusal before HeardEnd had written the discard, so a reader right after saw
nothing decided. The question path keeps the same order.
This commit is contained in:
jochen
2026-10-12 22:51:21 +02:00
parent 9446bec2f9
commit e4e0ce7619
@@ -838,14 +838,20 @@ func HeardEnd(p Paths, store ProposalStore, w asks.Warrant, now time.Time) (stri
if !known || (w.About != "" && w.About != prop.Ask().About) {
return "", nil
}
endedMu.Lock()
ended[w.Ask] = w
endedMu.Unlock()
// Said to a proposer waiting on it only once the discard is kept: what it reads next is already there (the
// flake of the router's refusal test under a loaded build agent, 2026-10-12).
tell := func() {
endedMu.Lock()
ended[w.Ask] = w
endedMu.Unlock()
}
approved, err := ReadApproved(p)
if err != nil {
tell()
return "", err
}
if _, done := approved.Decided[w.Ask]; done {
tell()
return "", nil
}
// Heard, not read from a record: Reconcile still reads the router's record of it, so an ask the router took after
@@ -856,7 +862,9 @@ func HeardEnd(p Paths, store ProposalStore, w asks.Warrant, now time.Time) (stri
}
approved.Decided[w.Ask] = d
delete(approved.Refused, w.Ask)
if err := writeApproved(p, approved); err != nil {
err = writeApproved(p, approved)
tell()
if err != nil {
return "", err
}
return "proposal " + w.Ask + ": " + d.Outcome, nil