From b7f78d47c5c4ee3f1eb915f044c544f2de2c58d5 Mon Sep 17 00:00:00 2001 From: jochen Date: Tue, 10 Nov 2026 03:00:58 +0100 Subject: [PATCH] Review parts are asked one at a time: the node judges one at a time, a second ask only spent its bound waiting (issue 1966, quick fix) Claude-Session: https://claude.ai/code/session_01JG73KK8HD1gufnqyFxMFdW --- modules/mesh-knowledge/cmd/mesh-knowledge/review_parts.go | 5 +++-- .../mesh-knowledge/cmd/mesh-knowledge/review_parts_test.go | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/modules/mesh-knowledge/cmd/mesh-knowledge/review_parts.go b/modules/mesh-knowledge/cmd/mesh-knowledge/review_parts.go index d4fa6b428..ab4492e04 100644 --- a/modules/mesh-knowledge/cmd/mesh-knowledge/review_parts.go +++ b/modules/mesh-knowledge/cmd/mesh-knowledge/review_parts.go @@ -25,8 +25,9 @@ const HeadPart = "head" // MostFrameBytes is the most the frame of a section part holds. const MostFrameBytes = 16 << 10 -// MostParallelParts is how many judgements of one version run at once. -const MostParallelParts = 2 +// MostParallelParts is how many judgements of one version run at once. The node runs one judgement at a time (ADR 0278 +// ยง25), so a second ask would only spend its own bound waiting for the first (issue 1966). +const MostParallelParts = 1 // PartReview is the latest verdict of one part: the digest of what it was judged with, so a part whose text and frame are // unchanged keeps it. diff --git a/modules/mesh-knowledge/cmd/mesh-knowledge/review_parts_test.go b/modules/mesh-knowledge/cmd/mesh-knowledge/review_parts_test.go index 3e949ac95..8fb5ac711 100644 --- a/modules/mesh-knowledge/cmd/mesh-knowledge/review_parts_test.go +++ b/modules/mesh-knowledge/cmd/mesh-knowledge/review_parts_test.go @@ -20,7 +20,7 @@ func TestAVersionIsReviewedInPartsAndARevisionJudgesOnlyWhatChanged(t *testing.T var asked []string var failOn string inner := w.k.Judge - // The first two judgements wait for each other, so the test sees them run at once and not one after the other. + // The first judgement is counted at once; the test sees that no second one runs beside it. var arrived atomic.Int32 meet := make(chan struct{}) w.k.Judge = func(q string, s map[string]any, model string) (json.RawMessage, string, error) { @@ -63,8 +63,8 @@ func TestAVersionIsReviewedInPartsAndARevisionJudgesOnlyWhatChanged(t *testing.T if e.Current.Status != StatusProposed || e.Current.Judging == nil || e.Current.Judging.State != JudgingFailed || len(e.Current.Parts) != 4 { t.Fatalf("%v: %s, %+v, %d parts", said, e.Current.Status, e.Current.Judging, len(e.Current.Parts)) } - if most.Load() > MostParallelParts || most.Load() < 2 { - t.Fatalf("%d judgements at once; at most %d, and the parts run side by side", most.Load(), MostParallelParts) + if most.Load() != 1 || MostParallelParts != 1 { + t.Fatalf("%d judgements at once; exactly 1 (the node judges one at a time), const %d", most.Load(), MostParallelParts) } if got := len(w.said.of(EventPartReviewed)); got != 4 || len(w.said.of(EventReviewed)) != 1 { t.Fatalf("part-reviewed %d, reviewed %d", got, len(w.said.of(EventReviewed)))