import assert from "node:assert/strict"; import { test } from "node:test"; // **The forge's announcements carry a message id** (novox/hq ADR 0406 §6, §7, issue 976): the same announcement, // however many paths make it — the poll, the forge's event, the merge tool's ask — has one id, which the runtime makes // the bus's message id, so the bus stores it once. This replaces the files of what was announced. const merged = { owner: "novox", repo: "app", number: 7, head_sha: "aaa111", merge_commit_sha: "mmm222", base: "main" }; const updated = { owner: "novox", repo: "app", number: 7, head_sha: "aaa111", base_sha: "ttt333", base: "main" }; const closed = { owner: "novox", repo: "app", number: 7, head_sha: "aaa111", base: "main" }; test("the same merge, head or close announced twice has the same id, and another has another", async () => { const { announcementId } = await import("../announce.ts"); assert.equal(announcementId("pull.merged", merged), "merged:novox/app#7@mmm222"); assert.equal(announcementId("pull.merged", { ...merged, title: "worded differently" }), announcementId("pull.merged", merged)); assert.notEqual(announcementId("pull.merged", { ...merged, merge_commit_sha: "other" }), announcementId("pull.merged", merged)); assert.equal(announcementId("pull.updated", updated), "updated:novox/app#7@aaa111:ttt333"); assert.notEqual(announcementId("pull.updated", { ...updated, base_sha: "moved" }), announcementId("pull.updated", updated), "the check asked again against a new trunk commit is another announcement"); assert.notEqual(announcementId("pull.updated", { ...updated, head_sha: "bbb" }), announcementId("pull.updated", updated)); assert.equal(announcementId("pull.updated", { ...updated, base_sha: undefined }), "updated:novox/app#7@aaa111:"); assert.equal(announcementId("pull.closed", closed), "closed:novox/app#7@aaa111"); }); test("an announcement is said on the seat git with its id, in the contract's body, never the description", async () => { const { useRuntime } = await import("@novox/mesh-sdk/runtime"); const said: any[] = []; useRuntime(async (method, params) => { said.push({ method, ...(params as object) }); return null; }); const { announce } = await import("../announce.ts"); const { seatEventOf, SEAT_ONLY } = await import("../seatevents.ts"); await announce("pull.merged", { ...merged, body: "a description", head: "feat/x", paths: ["a/b.go"], removed: [] }); await announce("pull.merged", { ...merged }); useRuntime(undefined); assert.equal(said.length, 2); assert.deepEqual([said[0].method, said[0].subject, said[0].id], ["mesh/seat.publish", "mesh.seat.git.event.pull-merged", "merged:novox/app#7@mmm222"]); assert.equal(said[1].id, said[0].id, "one id for one announcement"); assert.deepEqual(said[0].body, { repository: "novox/app", number: 7, base: "main", branch: "feat/x", head: "aaa111", "merge-commit": "mmm222", change: { paths: ["a/b.go"] } }); // Every event the seat says, from what the module's paths make; the others are none of the seat's. const rows: [string, Record, string | undefined][] = [ ["pull.updated", updated, "mesh.seat.git.event.pull-updated"], ["pull.closed", closed, "mesh.seat.git.event.pull-closed"], ["forge.status", { full_name: "novox/app", sha: "aaa111", context: "mesh/check", state: "success" }, "mesh.seat.git.event.forge-status"], ["forge.delete", { owner: "novox", repo: "app", ref: "feat/x", ref_type: "branch" }, "mesh.seat.git.event.forge-delete"], ["repo.writable", { owner: "novox", repo: "app", account: "mesh-tools" }, "mesh.seat.git.event.repo-writable"], ["forge.pull-request.synchronized", { full_name: "novox/app", number: 7, head_sha: "aaa111" }, "mesh.seat.git.event.forge-pull"], ["forge.pull-request.labeled", { full_name: "novox/app", number: 7 }, undefined], ["forge.push", { full_name: "novox/app", ref: "refs/tags/v1", after: "a".repeat(40) }, undefined], ["forge.push", { full_name: "novox/app", ref: "refs/heads/gone", after: "0".repeat(40) }, undefined], ["forge.push", { full_name: "novox/app", ref: "refs/heads/feat/x", after: "a".repeat(40) }, "mesh.seat.git.event.branch-moved"], ]; for (const [type, body, subject] of rows) assert.equal(seatEventOf(type, body)?.subject, subject, type); assert.deepEqual(seatEventOf("pull.updated", updated)?.body, { repository: "novox/app", number: 7, base: "main", branch: "", head: "aaa111", "base-head": "ttt333" }); assert.equal(seatEventOf("forge.pull-request.edited", { full_name: "novox/app", number: 7, body: "x" })?.body && "body" in (seatEventOf("forge.pull-request.edited", { full_name: "novox/app", number: 7, body: "x" })!.body as object), false); // A push of a branch (a merge and an admitted push alike) says branch-moved with the new head, one id per move. const moved = seatEventOf("forge.push", { full_name: "novox/app", ref: "refs/heads/main", after: "b".repeat(40) }, () => new Date("2026-11-11T10:00:00Z")); assert.deepEqual(moved?.body, { repository: "novox/app", branch: "main", head: "b".repeat(40), at: "2026-11-11T10:00:00.000Z" }); assert.equal(moved?.id, `moved:novox/app:main@${"b".repeat(40)}`); assert.deepEqual([...SEAT_ONLY].sort(), ["forge.delete", "forge.status", "pull.closed", "pull.merged", "pull.updated", "repo.writable"]); }); test("an announcement of a kind it has no id for is refused, never published with a made-up one", async () => { const { announce, announcementId } = await import("../announce.ts"); assert.equal(announcementId("repo.created", { owner: "a" }), undefined); await assert.rejects(() => announce("repo.created", { owner: "a" }), /not an announcement with a message id/); }); test("the watermark is kept in the module's state, and an unreachable state is no record", async () => { const { readWatermark, keepWatermark } = await import("../announce.ts"); const kept = new Map(); const store = { get: async (k: string) => (kept.has(k) ? { key: k, value: kept.get(k), revision: 1 } : null), put: async (k: string, v: unknown) => { kept.set(k, v); return 1; } }; assert.equal(await readWatermark(store as any), "", "none yet"); await keepWatermark("2026-10-17T12:00:00.000Z", store as any); assert.equal(await readWatermark(store as any), "2026-10-17T12:00:00.000Z"); const away = { get: async () => { throw new Error("no runtime"); }, put: async () => { throw new Error("no runtime"); } }; assert.equal(await readWatermark(away as any), "", "a state that cannot be reached is no record"); await keepWatermark("2026-10-17T12:01:00.000Z", away as any); // said, not thrown });