Say a pull request nobody checks as a delivery held, owned by mesh-delivery (hq issue 347)
mesh/merge-gate pass: builds gitea, mesh-delivery → novox; no bus step; every machine composes with the change as it did without (4 of 4 compose)
mesh/repo-check pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)
mesh/delivery superseded: a newer delivery to the same trunk took over its walk

The confirmation review asked for the delivery domain's own vocabulary
instead of a provider standing. A gitea health check would need a `tools`
list (turning gitea's tools into seat verbs), a check of another kind
beside it, and would hold the forge's own deliveries at the first-node
gate; so the delivery's owner says it, with the word it already has.

- gitea_open_pulls (gitea): every open pull request from the forge itself,
  with what its base requires and the statuses its head has.
- mesh-delivery asks it every five minutes and keeps its own first-seen
  time per head (the forge's update time moves on every comment). A head
  on a base requiring mesh/merge-gate OR mesh/repo-check (hq requires only
  the second) with neither for ten minutes is a `stalled` line in state
  `unannounced`, which the controller raises as delivery.<id>.stalled (D14);
  H2 has nothing to close. Once announced it is a delivery of its own.
- The gitea-side watcher and its provider standing are gone.
This commit is contained in:
jochen
2026-10-09 13:14:36 +02:00
parent bcc6b3f52a
commit 32d55beb47
16 changed files with 323 additions and 110 deletions
-25
View File
@@ -113,31 +113,6 @@ export function reposToLook(repos: GiteaRepo[], floor: string, pulls: PullSeen[]
return repos.filter((r) => moved.has(r.full_name));
}
/** How long a head may go without a merge check before it is said: the announcer's passes are half a minute
* apart and the check is asked at once, so ten minutes is a fault, never a queue. */
export const UNANNOUNCED_AFTER_MS = 10 * 60_000;
/** An open pull request as the watcher of announcements reads it. */
export interface OpenPull {
/** `owner/repo#number`. */
key: string;
base: string;
head_sha: string;
/** When its head last moved, or it was opened or retargeted. */
updated_at?: string;
/** The status contexts its head has, any state. */
statuses: string[];
/** The contexts its base branch's protection requires. */
required: string[];
}
/** The open pull requests whose base requires the merge check and whose head has had none for ten minutes
* (novox/hq issue 347): announced by nobody, checked by nothing, and blocked from merging with no word why. */
export function unannounced(pulls: OpenPull[], now: number, after = UNANNOUNCED_AFTER_MS): OpenPull[] {
return pulls.filter((p) => p.required.includes(CHECK_CONTEXT) && !p.statuses.includes(CHECK_CONTEXT) &&
!!p.updated_at && now - Date.parse(p.updated_at) >= after);
}
// **A required status is success or it blocks** (novox/hq issue 293). The forge combines `warning` as a
// failure, and a branch whose protection requires mesh/merge-gate or mesh/repo-check — with no
// administrator override — will not merge past one. So the controller's `warning`, a note and never a