diff --git a/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/adr548_test.go b/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/adr548_test.go index 89d97b1b..a10f167c 100644 --- a/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/adr548_test.go +++ b/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/adr548_test.go @@ -203,6 +203,37 @@ func TestOneCheckPerDeliveryAtTheGate(t *testing.T) { t.Errorf("after the carry: verdict %+v, merges %v; want merged on the carried verdict", d.Check, w.forge.merges) } }, + // §4: delivery_turns reads every turn with the check it waits for; delivery_hand_now hands a held merge at once on the + // operator's word, and refuses one no check holds. + "the turns are read, and a held merge is handed now on the operator's word": func(t *testing.T) { + w := newWorld(t) + w.h.Turns = newMemTurns(w) + putCheckerVerdict(w, "running", headOf(oneRepo, 9, otherHead)) + id := approvedLone(w) + w.settleAll() + read := w.h.TurnsRead() + lines := read["turns"].([]TurnLine) + if len(lines) != 1 || lines[0].Repository != oneRepo || len(lines[0].Turn.Waiting) != 1 || lines[0].Turn.Waiting[0].WaitsFor == "" || + !strings.Contains(lines[0].Waits["feat/one"].(string), "the check g.") || read["written"] != true { + t.Fatalf("delivery_turns = %+v", read) + } + if _, err := w.h.HandNow(id, ""); err == nil || !strings.Contains(err.Error(), "why") { + t.Errorf("a hand without the operator's why: %v", err) + } + if _, err := w.h.HandNow(IDOf(oneRepo2, oneHead2), "x"); err == nil { + t.Error("an unknown delivery was handed") + } + if _, err := w.h.HandNow(id, "the operator, on telegram: merge it now"); err != nil { + t.Fatal(err) + } + w.settleAll() + if len(w.forge.merges) != 1 || w.delivery(id).Ready.HandNow == "" { + t.Fatalf("merges %v after the hand", w.forge.merges) + } + if _, err := w.h.HandNow(id, "again"); err == nil { + t.Error("a merged delivery was handed again") + } + }, } { t.Run(name, run) } diff --git a/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/main.go b/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/main.go index e2f35d20..e5fe73af 100644 --- a/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/main.go +++ b/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/main.go @@ -358,6 +358,24 @@ func tools(h *Holder, l *listening) []stdio.Tool { } return h.Close(strArg(a, "id"), strArg(a, "why")) }}, + {Name: "delivery_turns", + Description: "Every merge turn (novox/hq ADR 0548 §3): per repository, the approved merges that wait to merge into it in the order of " + + "their Approve, the check of another delivery each waits for and since when, whether the gate wrote the turn to its bucket " + + "turns yet (the checker claims no check of a repository a turn names), and the bound past which a held merge is a stalled " + + "line. Read-only.", + Run: func(map[string]any) (any, error) { return h.TurnsRead(), nil }}, + {Name: "delivery_hand_now", + Description: "On the operator's word, hand an approved merge held for another delivery's running check to the merge at once " + + "(novox/hq ADR 0548 §4): the check it waited for runs on and is carried to the new trunk after the merge. Refused for a " + + "delivery that is not an approved merge held by a check, naming why. The why is kept on the delivery.", + Input: map[string]any{"type": "object", "properties": map[string]any{"id": str("the delivery's id (owner/repository@commit)"), + "why": str("the operator's word, kept on the delivery")}, "required": []string{"id", "why"}}, + Run: func(a map[string]any) (any, error) { + if err := need(a, "id", "why"); err != nil { + return nil, err + } + return h.HandNow(strArg(a, "id"), strArg(a, "why")) + }}, {Name: "delivery_status", Description: "Whether this owner works: how many deliveries in each state, the groups, what is owed to " + "the forge and the bus and not yet done, how many owed effects were tried since it started (done, failed " + diff --git a/modules/mesh-delivery-gate/module.json b/modules/mesh-delivery-gate/module.json index da631307..4a4e32f2 100644 --- a/modules/mesh-delivery-gate/module.json +++ b/modules/mesh-delivery-gate/module.json @@ -72,7 +72,9 @@ "mesh-delivery-checker.verdicts" ], "tools": [ - "delivery_status" + "delivery_hand_now", + "delivery_status", + "delivery_turns" ], "config": { "refusal-stall-floor-minutes": {