Answer what the mesh's checks said of a pull request, as mesh-delivery's checks verb (hq ADR 0239)
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
mesh/delivery superseded: a newer delivery to the same trunk took over its walk
mesh/delivery-group group feat/delivery-checks-verb delivered: every member is delivered

Reading a pull request's mesh/merge-gate and mesh/repo-check meant scraping the controller's journal:
the forge clips each status to 140 characters and nothing returned the verdict whole. mesh-delivery
already keeps the verdict; it now keeps the machine that ran it, the layers' modules and the report,
and its checks verb joins that to the forge's statuses, read through a new gitea_commit_statuses tool
that also says whether the base's protection lets the commit merge.

after: novox/mesh-controller
This commit is contained in:
jochen
2026-10-07 19:36:41 +02:00
parent c74f407abd
commit 13894744a7
14 changed files with 919 additions and 15 deletions
+42
View File
@@ -12,6 +12,7 @@ import { registerModuleTools, type ToolDefinition } from "@novox/mesh-sdk/tools"
import { emit } from "@novox/mesh-sdk/events";
import { GiteaClient, type BranchProtection } from "../client.js";
import { appendNote, deliveryStatus, run, viewBody, viewComment } from "../delivery.js";
import { mergeableUnder, newestByContext } from "../checks.js";
/** The forge's container, where its repositories and git are: the note is written there (novox/hq ADR 0239). */
const forgeContainer = process.env.MESH_GITEA_CONTAINER || "gitea";
@@ -450,6 +451,47 @@ export function getGiteaTools(gitea: GiteaClient): ToolDefinition[] {
return { created: await gitea.addComment(owner, repo, number, body) };
},
},
{
name: "gitea_commit_statuses",
description: "Read a commit's statuses — or a pull request's head's — as the forge keeps them: the newest of each context (mesh/merge-gate, mesh/repo-check, mesh/delivery, …) with its state, description, link, when it was set and by whom; and whether the branch it merges into would let it merge, every status that branch's protection requires being a success. Reads only.",
input: {
owner: { type: "string", description: "the repository owner" },
repo: { type: "string", description: "the repository name" },
number: { type: "number", description: "a pull request's number: its head is read, and its base's protection" },
sha: { type: "string", description: "a commit, or the start of one, instead of a pull request" },
base: { type: "string", description: "with sha: the branch whose protection is read (default main)" },
},
run: async (args) => {
const owner = String(args.owner ?? "").trim(), repo = String(args.repo ?? "").trim();
const number = args.number === undefined || args.number === "" ? 0 : Number(args.number);
let ref = String(args.sha ?? "").trim();
let base = String(args.base ?? "").trim();
if (!owner || !repo) throw new Error("name the repository: owner and repo");
if (!Number.isInteger(number) || number < 0) throw new Error(`${args.number} is not a pull request's number`);
let pull: { number: number; title: string; state: string; merged: boolean; base?: string; head?: string;
head_sha?: string; merge_commit_sha?: string; html_url: string } | undefined;
if (number > 0) {
const p = await gitea.getPullRequest(owner, repo, number);
pull = { number: p.number, title: p.title, state: p.state, merged: p.merged, base: p.base, head: p.head,
head_sha: p.head_sha, merge_commit_sha: p.merge_commit_sha, html_url: p.html_url };
if (!ref) ref = p.head_sha ?? "";
if (!base) base = p.base ?? "";
if (!ref) throw new Error(`${owner}/${repo}#${number} names no head commit`);
}
if (!ref) throw new Error("name a pull request's number or a commit");
const combined = await gitea.combinedStatus(owner, repo, ref);
const statuses = newestByContext(combined.statuses);
base = base || "main";
let rule: BranchProtection | null = null, unreadable: string | undefined;
try {
rule = await gitea.branchProtection(owner, repo, base);
} catch (err) {
unreadable = err instanceof Error ? err.message : String(err);
}
return { commit: combined.sha || ref, pull, combined: combined.state, statuses,
merge: mergeableUnder(base, rule, statuses, unreadable) };
},
},
{
name: "gitea_commit_status",
description: "Set one of the mesh's statuses on a commit (mesh/delivery, mesh/delivery-group): pending, success, error, failure or warning, a short description, and the page it links to.",