Files
mesh-catalog/modules/mesh-delivery-gate
jschoubben 099605ec70
mesh/delivery merged: source.main moved to novox/mesh-catalog@53bf4bb84cb1
mesh/check checking 099605ec70a2 on 53bf4bb84cb1
mesh-delivery-gate: the Approve's ask says the check's actual state at its heads, never a pass it has not had (issue 1733)
With check-gates-merge false a head is ready and asked before any verdict exists, yet the ask said "<pr> passed its
checks" (a group: "passed its checks"): on 2026-10-26 the operator approved mesh-delivery #79 and a six-repository group
on that claim while their checks had not answered.

The ask now reads the checker's verdict at exactly the heads it covers (checkAt, beside checkerAt): "passed its check"
only for a pass there; otherwise "its check has no verdict yet[: it is running (since HH:MM UTC)]" or "its check failed:
<first failure>", and the Approve clause says it merges "now, before its check ends" or "although its check failed".
While the check gates no merge, a pending ask whose check then passes or fails (or loses a pass it named) is withdrawn
and asked again in new words (the ask's AskCheck against the state now, endStaleAsks, the review-record path's
withdrawAsk); a check that starts running is no new word, so the wait stays one message. Whether a merge waits is
unchanged. The gate's log lines and stalled lines that claimed a pass for a ready head say the same state.

Quick fix: replace "passed its checks" by neutral words in the two summaries. Thorough fix: one reader of the check's
state at the ask's heads (checkAt) used by every text that names it, and the ask re-said when that state changes.
Chosen: thorough, as it costs one helper and one case in endStaleAsks, and the quick one would still leave a pending
ask silent about a failure that came after it.

Tests: rows in TestAnApprovedPullRequestIsMergedThroughTheMergeTool (gated pass; ungated no verdict, running, then
passed, then failed) and the ungated group's wording; no new test function.
2026-10-26 22:18:08 +01:00
..

mesh-delivery-gate

The mesh-delivery-gate module of the mesh catalogue: the gate of design 47. It claims the seat mesh-delivery, whose name stays (ADR 0437 §11), and takes over from the module mesh-delivery (ADR 0437 §3, ADR 0450 §6). Its buckets are mesh-delivery-gate_*.

Files it does not know

Each directory or archive this module declares says how it treats a file it did not write (ADR 0422, ADR 0416).

  • ${dir:state}: everything in it is the program's; the mesh moves nothing out (ADR 0422 §2).

What it keeps (ADR 0539 §17)

The gate keeps the merge's states: proposed, ready, rejected, merged, held (a merge that reached the trunk without a passing check) and closed. It asks the operator's Approve and merges once, moving source.main. It asks the controller nothing, follows no plan event and derives nothing after the merge: whether a merged change reached the machines is the view's, from source.main, the wants and the haves. The seat mesh-delivery keeps the verbs deliveries, show, groups, checks, table, stalled (for a merge or a check past its bound), recheck and close; times, what-if, release, stop and retire-history went with the plans, so the gate stays a bundle serving the seat. A delivery an earlier owner kept in a state that is gone is read as the state it came to (merged, closed or proposed) when the gate starts.

When a refused or rejected merge is said (ADR 0505 §4, §5)

stalled is what the gate says to the operator as conditions, itself, on the operator-channel seat (ADR 0437 §9, issue 1275): after every look it raises each line, raises it again when its severity or need changes, and clears each that is listed no more; its bucket conditions keeps which it raised. (The controller's self-check that raised them went in release 6.) The gate's own list (show, deliveries) names every refusal and rejection at once, and the pull request is told at once; only stalled waits:

  • a merge refused because its trunk moved, whose check the gate asked again, is stalled only once that check answered and the merge was refused again, or twice the repository's last check time passed (at least the setting refusal-stall-floor-minutes, 10). Every other refusal is stalled at once.
  • a delivery that needs its author's new head (its check failed after its Approve: a conflict, a failed check, a rejected group) is stalled only once no new head came for the setting author-new-head-minutes (120). Its line says needs: new-head and names its author: the branch, and the session a Pushed-by: <who@node> line in the pull request's description names.

A merge the forge account cannot carry out is not asked (issue 1945)

Before the operator's Approve is asked, the gate reads through gitea_commit_statuses whether the forge's merging account writes each repository the ask covers (merge.writes). Where it does not, nothing is asked: the delivery waits on "the forge account cannot write : gitea_grant_write" (show), raised at once as a condition. The read holds until the gitea module's gitea.repo.writable (its grant, read back) or ten minutes, then the ask is made again; an approved merge of that repository the forge refused is asked again on the same event (writes.go).

The seat's hand-over

The gate took the seat mesh-delivery over from the module mesh-delivery (ADR 0449 §4, ADR 0450 §6, ADR 0454) and carried its deliveries, groups and pull keys once; the carry, and the reading of the controller's assignments and the node-engine's have keys that waited for it, went with release 6. catalogue_test.go keeps the catalogue to one claimant of the seat.