// **mesh/check is written from the forge bridge's own event, never from a tool** (review finding K1 of R4e; novox/hq issue // 1301; ADR 0447 §1, ADR 0503 §3, ADR 0513 §4: main requires mesh/check alone). // // A tool is told no caller, and the console every agent session speaks through (node-tools) invokes every tool, so a tool // that wrote mesh/check could be called by any session to pass a merge past the checker: the fault issue 293 closed for // the two statuses before it. So the checker's forge bridge emits `check.status` instead. The bus grants the subject // mesh.mod.mesh-delivery-forge-bridge.event.check.status to the bridge's own account alone (its manifest's `emits`; a // module publishes under its own name only), and the bridge runs on that account, never carried by a machine's tool // runner. This module consumes the event, as it consumes mesh-controller.checked, and writes the status. // // The event's body: owner, repo, sha (the head, whole), state, description, target_url, key (the checker's owed key) and // revision (that key's revision in the checker's bucket). Its source is checked against the bridge too: the bus already // said it, and a body read from elsewhere says it again. Delivery is at-least-once and a failed write is delivered again // later, so a head's revision older than one already written is dropped: a stale pending never hides a verdict. import type { CommitStatus } from "./client.js"; import { checkName } from "./guard.js"; import { CHECK_STATUS } from "./pulls.js"; /** The module that alone writes mesh/check, and the event it writes it with. */ export const CHECK_WRITER = "mesh-delivery-forge-bridge"; export const CHECK_EVENT = `${CHECK_WRITER}.check.status`; const states = new Set(["pending", "success", "error", "failure", "warning"]); /** What writing the check needs of the forge. */ export interface CheckForge { setCommitStatus(owner: string, repo: string, sha: string, status: CommitStatus): Promise; } /** An event as the SDK's `on` hands it. */ export interface CheckEvent { source: string; id?: string; body: unknown; } /** The status a check.status asks for, checked; or why it is not one. */ export function checkStatusOf(body: unknown): { owner: string; repo: string; sha: string; revision: number; status: CommitStatus } { if (!body || typeof body !== "object") throw new Error("the event carries no body"); const b = body as Record; const owner = checkName("owner", b.owner), repo = checkName("name", b.repo); const sha = String(b.sha ?? ""); if (!/^([0-9a-f]{40}|[0-9a-f]{64})$/i.test(sha)) throw new Error(`${JSON.stringify(b.sha)} is not a head's whole sha`); if (b.context !== undefined && b.context !== null && b.context !== CHECK_STATUS) { throw new Error(`${JSON.stringify(b.context)}: check.status writes ${CHECK_STATUS} alone`); } const state = String(b.state ?? ""); if (!states.has(state)) throw new Error(`${JSON.stringify(b.state)} is not a status the forge keeps`); const revision = b.revision; if (typeof revision !== "number" || !Number.isSafeInteger(revision) || revision < 0) { throw new Error(`${JSON.stringify(revision)} is not a revision of the checker's owed key`); } let description = String(b.description ?? "").replace(/\s+/g, " ").trim(); if (description.length > 140) description = description.slice(0, 139) + "…"; const target = typeof b.target_url === "string" && /^https?:\/\//.test(b.target_url) ? b.target_url : undefined; const status: CommitStatus = { state: state as CommitStatus["state"], context: CHECK_STATUS, description, ...(target ? { target_url: target } : {}) }; return { owner, repo, sha, revision, status }; } /** The one writer of mesh/check: each check.status the bridge emits, in revision order per head. */ export class CheckStatuses { /** The newest revision written on each head, owner/repo@sha; the oldest heads go past what any forge holds open. */ private written = new Map(); /** The turn each head's writes wait on. */ private turns = new Map>(); private forge: CheckForge; private say: (line: string) => void; constructor(forge: CheckForge, say: (line: string) => void = (l) => console.error(l)) { this.forge = forge; this.say = say; } /** Write the event's status: "written", or "dropped" for one that is not the bridge's, malformed or stale. A forge * that refuses throws, so the bus delivers the event again. */ async apply(event: CheckEvent): Promise<"written" | "dropped"> { if (event.source !== CHECK_WRITER) { this.say(`[gitea] a check.status from ${JSON.stringify(event.source)}, not the forge bridge, is dropped: mesh/check is the bridge's alone`); return "dropped"; } let asked; try { asked = checkStatusOf(event.body); } catch (err) { this.say(`[gitea] the forge bridge's check.status ${event.id ?? ""} is dropped: ${err instanceof Error ? err.message : err}`); return "dropped"; } const head = `${asked.owner}/${asked.repo}@${asked.sha}`.toLowerCase(); // One head's writes take turns, so two deliveries at once are weighed one after the other. const before = this.turns.get(head) ?? Promise.resolve(); const turn = before.then(async (): Promise<"written" | "dropped"> => { const newest = this.written.get(head); if (newest !== undefined && asked.revision < newest) { this.say(`[gitea] ${asked.owner}/${asked.repo}@${asked.sha.slice(0, 12)}: mesh/check at revision ${asked.revision} is older than ${newest}, already written, and is dropped`); return "dropped"; } await this.forge.setCommitStatus(asked.owner, asked.repo, asked.sha, asked.status); this.written.delete(head); this.written.set(head, asked.revision); if (this.written.size > 2000) this.written.delete(this.written.keys().next().value as string); return "written"; }); const settled = turn.then(() => {}, () => {}); this.turns.set(head, settled); void settled.then(() => { if (this.turns.get(head) === settled) this.turns.delete(head); }); return turn; } }