import assert from "node:assert/strict"; import { test } from "node:test"; // **A pending check says where it is, and the verdict lands last** (novox/hq issue 446). This module is the one writer // of a head's mesh/merge-gate: the announcement's pending words, "building on since …" when the build seat // says a machine took the check, and the verdict. The forge keeps the newest status of a context, so a pending word // written after the verdict hides it — a pass reads pending, a failure hides under "building". const SHA = "a6b08de8507c1703528277e5cefc80548dbc9bb3"; // The build seat's `started` as a machine said it for novox/hq#309's check on 2026-10-11 (its log, read with the // controller's `builds --log build-1791680941048622697`, opens at 03:09:01 on shanks); only the forge's address // replaced. The shape is mesh-controller's link.BuildStart. const startedOnShanks = { id: "build-1791680941048622697", repository: "http://127.0.0.1:20000/novox/hq.git", ref: SHA, on: "shanks", at: "2026-10-11T01:09:01.204319Z" }; /** A forge that keeps the newest status per context, as gitea does, and whose writes take as long as a test says. */ function aForge() { const kept: Record = {}; const written: string[] = []; /** Every mesh/merge-gate status the forge was given, newest first, as gitea keeps each one. */ const history: { state: string; description: string; updated_at: string }[] = []; let failNext = 0; let hold: Promise | null = null; let release = () => {}; let readHold: Promise | null = null; let readRelease = () => {}; return { kept, written, history, /** The next writes fail: a request the forge did not take. */ failWrites(n = 1) { failNext = n; }, /** The next writes wait until released: a request in flight. */ holdWrites() { hold = new Promise((r) => (release = r)); }, release() { hold = null; release(); }, async setCommitStatus(_o: string, _r: string, _sha: string, s: { state: string; context: string; description: string }) { if (hold) await hold; if (failNext > 0) { failNext--; throw new Error("the forge answered 502"); } kept[s.context] = { state: s.state, description: s.description, updated_at: new Date().toISOString() }; if (s.context === "mesh/merge-gate") history.unshift(kept[s.context]); written.push(`${s.state} ${s.description}`); }, /** Reads answer what the forge held when asked, as late as the reads are held: the answer of a request in flight. */ holdReads() { readHold = new Promise((r) => (readRelease = r)); }, releaseReads() { readHold = null; readRelease(); }, async gateOf(_o: string, _r: string, _sha: string) { const held = kept["mesh/merge-gate"] ? { ...kept["mesh/merge-gate"] } : undefined; if (readHold) await readHold; return held; }, async gateHistory(_o: string, _r: string, _sha: string) { return history.map((h) => ({ ...h })); }, }; } /** The clock of the test: the head announced at 01:08:50Z. */ const announcedAt = () => new Date("2026-10-11T01:08:50Z"); test("a build machine taking the check is said on the head: building on which machine, since the local time", async () => { const { GateWriter, buildingWords } = await import("../gate.ts"); const forge = aForge(); const gates = new GateWriter(forge, announcedAt); await gates.pending("novox", "hq", SHA); assert.equal(await gates.started("novox", "hq", SHA, startedOnShanks), true); assert.equal(forge.kept["mesh/merge-gate"].state, "pending"); assert.equal(forge.kept["mesh/merge-gate"].description, buildingWords("shanks", new Date(startedOnShanks.at))); assert.equal(buildingWords("shanks", new Date(2026, 9, 11, 3, 9, 1)), "building on shanks since 03:09"); }); test("the verdict heard while a 'building' write is in flight lands last and stays", async () => { const { GateWriter } = await import("../gate.ts"); const forge = aForge(); const gates = new GateWriter(forge, announcedAt); await gates.pending("novox", "hq", SHA); forge.holdWrites(); // the 'building' request is in flight when the verdict comes const building = gates.started("novox", "hq", SHA, startedOnShanks); await new Promise((r) => setImmediate(r)); const verdict = gates.verdict("novox", "hq", SHA, () => forge.setCommitStatus("novox", "hq", SHA, { state: "success", context: "mesh/merge-gate", description: "pass" })); forge.release(); await Promise.all([building, verdict]); assert.equal(`${forge.kept["mesh/merge-gate"].state} ${forge.kept["mesh/merge-gate"].description}`, "success pass", `the verdict is not the newest status: ${forge.written.join(" | ")}`); }); // The race the review of mesh-catalog#202 reproduced: a writer reads the forge's gate (pending), the verdict is written, // then the writer writes "building" — and the pass reads pending until the next push. A head this process did not // announce is the one case where the forge is read before writing. test("the verdict written while a start's read of the forge is in flight stays the newest status", async () => { const { GateWriter } = await import("../gate.ts"); const forge = aForge(); forge.kept["mesh/merge-gate"] = { state: "pending", description: "waiting", updated_at: "2026-10-11T01:08:50Z" }; const gates = new GateWriter(forge, announcedAt); forge.holdReads(); const building = gates.started("novox", "hq", SHA, startedOnShanks); await new Promise((r) => setImmediate(r)); const verdict = gates.verdict("novox", "hq", SHA, () => forge.setCommitStatus("novox", "hq", SHA, { state: "success", context: "mesh/merge-gate", description: "pass" })); await new Promise((r) => setImmediate(r)); forge.releaseReads(); await Promise.all([building, verdict]); assert.equal(`${forge.kept["mesh/merge-gate"].state} ${forge.kept["mesh/merge-gate"].description}`, "success pass", `the verdict is not the newest status: ${forge.written.join(" | ")}`); }); test("the verdict heard while a 'building' write still waits its turn: the 'building' is never written", async () => { const { GateWriter } = await import("../gate.ts"); const forge = aForge(); const gates = new GateWriter(forge, announcedAt); forge.holdWrites(); // the pending words are still being written const pending = gates.pending("novox", "hq", SHA); const building = gates.started("novox", "hq", SHA, startedOnShanks); const verdict = gates.verdict("novox", "hq", SHA, () => forge.setCommitStatus("novox", "hq", SHA, { state: "failure", context: "mesh/merge-gate", description: "fail: 0 of 4 compose" })); forge.release(); await Promise.all([pending, verdict]); assert.equal(await building, false); assert.equal(forge.kept["mesh/merge-gate"].state, "failure"); assert.ok(!forge.written.some((w) => w.includes("building")), forge.written.join(" | ")); }); test("a start heard after the verdict writes nothing", async () => { const { GateWriter } = await import("../gate.ts"); const forge = aForge(); const gates = new GateWriter(forge, announcedAt); await gates.pending("novox", "hq", SHA); await gates.verdict("novox", "hq", SHA, () => forge.setCommitStatus("novox", "hq", SHA, { state: "success", context: "mesh/merge-gate", description: "pass" })); assert.equal(await gates.started("novox", "hq", SHA, startedOnShanks), false); assert.equal(forge.kept["mesh/merge-gate"].state, "success"); }); test("a start from before the check now pending (a run before a recheck, the stream's history) writes nothing", async () => { const { GateWriter } = await import("../gate.ts"); const forge = aForge(); let now = announcedAt(); const gates = new GateWriter(forge, () => now); await gates.pending("novox", "hq", SHA); await gates.verdict("novox", "hq", SHA, () => forge.setCommitStatus("novox", "hq", SHA, { state: "failure", context: "mesh/merge-gate", description: "error" })); now = new Date("2026-10-11T01:30:00Z"); // checked again: the recheck's pending, as the tool writes it (issue 456) await gates.rechecked("novox", "hq", SHA, { state: "pending", context: "mesh/merge-gate", description: "checking again: flaky" }); assert.equal(await gates.started("novox", "hq", SHA, startedOnShanks), false, "the first run's start"); assert.equal(forge.kept["mesh/merge-gate"].description, "checking again: flaky"); assert.equal(await gates.started("novox", "hq", SHA, { ...startedOnShanks, at: "2026-10-11T01:31:00Z" }), true, "the second run's start"); }); // **A recheck's pending goes through the one writer** (novox/hq issue 456). mesh-delivery's recheck puts the gate back // to pending through the gitea_commit_status tool; before, that write bypassed the head's chain: the first run's // verdict mark stayed set, so the new run never said "building", and an old run's verdict could land over the pending. /** The ask of a check, as the controller's link.NewBuildID names it: when it was asked, in unix nanoseconds. */ const askOf = (at: string) => `build-${BigInt(Date.parse(at)) * 1_000_000n}`; const firstRun = askOf("2026-10-11T01:09:01Z"); const recheckAt = new Date("2026-10-11T01:30:00Z"); const secondRun = askOf("2026-10-11T01:30:02Z"); const checkingAgain = { state: "pending" as const, context: "mesh/merge-gate", description: "checking again: main moved on" }; const writeOf = (forge: ReturnType, state: string, description: string) => () => forge.setCommitStatus("novox", "hq", SHA, { state, context: "mesh/merge-gate", description }); const gateOf = (forge: ReturnType) => `${forge.kept["mesh/merge-gate"].state} ${forge.kept["mesh/merge-gate"].description}`; test("an old run's verdict redelivered after a recheck's pending is not written over it", async () => { const { GateWriter } = await import("../gate.ts"); const forge = aForge(); let now = announcedAt(); const gates = new GateWriter(forge, () => now); await gates.pending("novox", "hq", SHA); forge.failWrites(); // the first run's verdict is not taken: the event is offered again await assert.rejects(gates.verdict("novox", "hq", SHA, writeOf(forge, "success", "pass"), firstRun)); now = recheckAt; await gates.rechecked("novox", "hq", SHA, checkingAgain); await gates.verdict("novox", "hq", SHA, writeOf(forge, "success", "pass"), firstRun); // redelivered assert.equal(gateOf(forge), "pending checking again: main moved on", forge.written.join(" | ")); // The recheck's own verdict is written. await gates.verdict("novox", "hq", SHA, writeOf(forge, "failure", "fail: 0 of 4 compose"), secondRun); assert.equal(gateOf(forge), "failure fail: 0 of 4 compose"); }); test("an old run's verdict in flight when the recheck comes lands before the recheck's pending", async () => { const { GateWriter } = await import("../gate.ts"); const forge = aForge(); let now = announcedAt(); const gates = new GateWriter(forge, () => now); await gates.pending("novox", "hq", SHA); forge.holdWrites(); // the first run's verdict is being written when the recheck comes const verdict = gates.verdict("novox", "hq", SHA, writeOf(forge, "success", "pass"), firstRun); await new Promise((r) => setImmediate(r)); now = recheckAt; const pending = gates.rechecked("novox", "hq", SHA, checkingAgain); forge.release(); await Promise.all([verdict, pending]); assert.equal(gateOf(forge), "pending checking again: main moved on", forge.written.join(" | ")); }); test("a rechecked head says where its new run is: building on which machine", async () => { const { GateWriter, buildingWords } = await import("../gate.ts"); const forge = aForge(); let now = announcedAt(); const gates = new GateWriter(forge, () => now); await gates.pending("novox", "hq", SHA); await gates.verdict("novox", "hq", SHA, writeOf(forge, "success", "pass"), firstRun); now = recheckAt; await gates.rechecked("novox", "hq", SHA, checkingAgain); const at = "2026-10-11T01:30:03Z"; assert.equal(await gates.started("novox", "hq", SHA, { ...startedOnShanks, id: secondRun, at }), true); assert.equal(forge.kept["mesh/merge-gate"].description, buildingWords("shanks", new Date(at))); }); test("the recheck's own verdict is written, even asked a little before the pending by another machine's clock", async () => { const { GateWriter } = await import("../gate.ts"); const forge = aForge(); const gates = new GateWriter(forge, () => recheckAt); await gates.rechecked("novox", "hq", SHA, checkingAgain); await gates.verdict("novox", "hq", SHA, writeOf(forge, "success", "pass"), askOf("2026-10-11T01:29:30Z")); assert.equal(gateOf(forge), "success pass"); // A verdict whose ask cannot be read is written: a verdict is never lost to what cannot be weighed. await gates.rechecked("novox", "hq", SHA, checkingAgain); await gates.verdict("novox", "hq", SHA, writeOf(forge, "failure", "fail"), "an id of another shape"); assert.equal(gateOf(forge), "failure fail"); }); test("after a restart, an old run's verdict is weighed against the check the forge's history holds open", async () => { const { GateWriter } = await import("../gate.ts"); const forge = aForge(); // What the forge kept before this process started: the announcement, the first run's verdict never written, // the recheck's pending, and the second run's "building" over it. forge.history.unshift({ state: "pending", description: "waiting in the build queue since 03:08", updated_at: "2026-10-11T01:08:50Z" }); forge.history.unshift({ state: "pending", description: "checking again: main moved on", updated_at: "2026-10-11T01:30:00Z" }); forge.history.unshift({ state: "pending", description: "building on shanks since 03:30", updated_at: "2026-10-11T01:30:05Z" }); forge.kept["mesh/merge-gate"] = forge.history[0]; const gates = new GateWriter(forge, announcedAt); await gates.verdict("novox", "hq", SHA, writeOf(forge, "success", "pass"), firstRun); assert.equal(forge.kept["mesh/merge-gate"].description, "building on shanks since 03:30", forge.written.join(" | ")); await gates.verdict("novox", "hq", SHA, writeOf(forge, "failure", "fail"), secondRun); assert.equal(gateOf(forge), "failure fail"); }); test("a recheck the forge does not take fails its caller, and the head is as it was", async () => { const { GateWriter } = await import("../gate.ts"); const forge = aForge(); let now = announcedAt(); const gates = new GateWriter(forge, () => now); await gates.pending("novox", "hq", SHA); forge.failWrites(); await assert.rejects(gates.verdict("novox", "hq", SHA, writeOf(forge, "success", "pass"), firstRun)); now = recheckAt; forge.failWrites(); await assert.rejects(gates.rechecked("novox", "hq", SHA, checkingAgain)); // The recheck was refused, so its check is not asked: the first run's verdict, offered again, is the head's. await gates.verdict("novox", "hq", SHA, writeOf(forge, "success", "pass"), firstRun); assert.equal(gateOf(forge), "success pass"); }); test("the status tool writes the merge check's pending through the writer, and the mesh's other statuses as they were", async () => { const { GateWriter } = await import("../gate.ts"); const { commitStatusTool } = await import("../delivery.ts"); const forge = aForge(); const direct: string[] = []; const gates = new GateWriter(forge, () => recheckAt); const tool = commitStatusTool({ setCommitStatus: async (_o, _r, _sha, s) => void direct.push(`${s.context} ${s.state}`), gates, }); await gates.verdict("novox", "hq", SHA, writeOf(forge, "success", "pass"), firstRun); await tool.run({ owner: "novox", repo: "hq", sha: SHA, context: "mesh/merge-gate", state: "pending", description: "checking again: x" }); await tool.run({ owner: "novox", repo: "hq", sha: SHA, context: "mesh/repo-check", state: "pending", description: "checking again: x" }); await tool.run({ owner: "novox", repo: "hq", sha: SHA, context: "mesh/delivery", state: "success", description: "delivered" }); assert.equal(gateOf(forge), "pending checking again: x"); assert.equal(forge.kept["mesh/repo-check"].state, "pending"); assert.deepEqual(direct, ["mesh/delivery success"]); // The redelivered first run's verdict is the writer's to drop. await gates.verdict("novox", "hq", SHA, writeOf(forge, "success", "pass"), firstRun); assert.equal(gateOf(forge), "pending checking again: x"); // A head named short is another head to the writer: refused, nothing sent. await assert.rejects(tool.run({ owner: "novox", repo: "hq", sha: SHA.slice(0, 12), context: "mesh/merge-gate", state: "pending" }), /whole sha/); await assert.rejects(tool.run({ owner: "novox", repo: "hq", sha: SHA, context: "mesh/merge-gate", state: "success" }), /set by its verdict only/); }); test("when a check was asked is read from its id; the opening of the check now pending from the gate's history", async () => { const { askedAt, openedAt } = await import("../gate.ts"); assert.equal(askedAt("build-1791680941048622697"), Date.parse("2026-10-11T01:09:01.048Z")); assert.equal(askedAt("build-mesh-catalog"), undefined); assert.equal(askedAt(undefined), undefined); assert.equal(openedAt([{ state: "pending", description: "building on ace since 03:31", updated_at: "2026-10-11T01:31:00Z" }, { state: "pending", description: "checking again: x", updated_at: "2026-10-11T01:30:00Z" }]), Date.parse("2026-10-11T01:30:00Z")); assert.equal(openedAt([{ state: "success", description: "pass", updated_at: "2026-10-11T01:30:00Z" }]), undefined); assert.equal(openedAt([]), undefined); }); test("a head this process did not announce (it restarted) is said only while the forge holds its gate pending", async () => { const { GateWriter } = await import("../gate.ts"); const forge = aForge(); forge.kept["mesh/merge-gate"] = { state: "success", description: "pass", updated_at: "2026-10-11T01:20:00Z" }; const gates = new GateWriter(forge, announcedAt); assert.equal(await gates.started("novox", "hq", SHA, startedOnShanks), false); forge.kept["mesh/merge-gate"] = { state: "pending", description: "waiting", updated_at: "2026-10-11T01:08:50Z" }; assert.equal(await gates.started("novox", "hq", SHA, startedOnShanks), true); }); test("a repository as the mesh clones it is told from another", async () => { const { clonedAs } = await import("../gate.ts"); assert.equal(clonedAs("http://127.0.0.1:20000/novox/hq.git", "novox", "hq"), true); assert.equal(clonedAs("http://127.0.0.1:20000/novox/mesh-hq.git", "novox", "hq"), false); assert.equal(clonedAs("http://127.0.0.1:20000/novox/mesh-controller.git", "novox", "hq"), false); });