/*
RFC-1297: unit tests for live-channel drift — readLiveChannelStates +
liveDriftDiagnostics. AC-3: live ≠ recorded produces a LIVE-01 error. AC-4:
unreachable produces a LIVE-02 warning. Channels without lastPropagated are
skipped.
- Not a contract source of truth — the module under test owns the authoritative behavior; fixtures are minimal scaffolding only.
- RFC-1297: initial — AC-3/AC-4 probes.
- RFC-1297
*/
import { test, expect, beforeEach, afterEach } from "vitest";
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { createDefaultIO } from "@warpgogol/werkstatt-shared/kernel/workspace-io";
import { readLiveChannelStates, liveDriftDiagnostics } from "./live-drift.ts";
const systemId = "acme";
let tmpDir: string;
let werkstattRoot: string;
function jsonResponse(status: number, body: unknown): Response {
return new Response(JSON.stringify(body), {
status,
headers: { "content-type": "application/json" },
});
}
beforeEach(() => {
tmpDir = mkdtempSync(join(tmpdir(), "live-drift-"));
werkstattRoot = join(tmpDir, "werkstatt");
const cacheDir = join(tmpDir, "systems-cache", systemId);
mkdirSync(werkstattRoot, { recursive: true });
mkdirSync(cacheDir, { recursive: true });
writeFileSync(
join(cacheDir, "system-config.yaml"),
[
"schemaVersion: 1.0.0",
`id: ${systemId}`,
"cosmicStar: Vega",
"mirrors:",
" - path: ../systems-cache/acme",
" storageType: non-bare",
"pinnedPlatform: 6.346.1",
"status: active",
"registeredAt: 2026-01-01T00:00:00.000Z",
"deployment:",
" adapter: cloudflare-workers",
" channels:",
" dev:",
" workerName: dev-acme",
" url: https://dev.example.com",
" alt:",
" workerName: alt-acme",
" url: https://alt.example.com",
" main:",
" workerName: acme",
" url: https://example.com",
"",
].join("\n"),
);
});
afterEach(() => {
rmSync(tmpDir, { recursive: true, force: true });
});
function writeState(lastPropagated: Record) {
const lines = [
"schemaVersion: 1.0.0",
`systemId: ${systemId}`,
"currentMission: null",
"lastRelease: null",
];
const entries = Object.entries(lastPropagated);
if (entries.length === 0) {
lines.push("lastPropagated: {}");
} else {
lines.push("lastPropagated:");
for (const [channel, entry] of entries) {
lines.push(
` ${channel}:`,
` releaseId: ${entry.releaseId}`,
" at: 2026-10-14T19:53:51.751Z",
" healthy: true",
" state: succeeded",
" operationId: op-test-0001",
" leaseExpiresAt: null",
);
}
}
writeFileSync(
join(tmpDir, "systems-cache", systemId, "system-state.yaml"),
lines.join("\n") + "\n",
);
}
test("AC-3: live releaseId differing from recorded produces a LIVE-01 error", async () => {
writeState({ main: { releaseId: "acme-r000036" } });
const fetchImpl = (async () => jsonResponse(200, { releaseId: "acme-r000035" })) as typeof fetch;
const states = await readLiveChannelStates({
workspaceRoot: werkstattRoot,
systemId,
io: createDefaultIO().io,
fetchImpl,
});
expect(states).toHaveLength(1);
expect(states[0].channel).toBe("main");
expect(states[0].recordedReleaseId).toBe("acme-r000036");
expect(states[0].liveReleaseId).toBe("acme-r000035");
const diagnostics = liveDriftDiagnostics(states, systemId);
const live01 = diagnostics.filter((d) => d.ruleId === "LIVE-01");
expect(live01).toHaveLength(1);
expect(live01[0].severity).toBe("error");
expect(live01[0].message).toContain("acme-r000035");
expect(live01[0].message).toContain("acme-r000036");
expect(live01[0].fixHint).toContain("leitstand.state.reconcile");
});
test("AC-4: unreachable channel produces a LIVE-02 warning, never an error", async () => {
writeState({ main: { releaseId: "acme-r000036" } });
const fetchImpl = (async () => {
throw new Error("connect ECONNREFUSED");
}) as typeof fetch;
const states = await readLiveChannelStates({
workspaceRoot: werkstattRoot,
systemId,
io: createDefaultIO().io,
fetchImpl,
});
const diagnostics = liveDriftDiagnostics(states, systemId);
expect(diagnostics.filter((d) => d.ruleId === "LIVE-01")).toHaveLength(0);
const live02 = diagnostics.filter((d) => d.ruleId === "LIVE-02");
expect(live02).toHaveLength(1);
expect(live02[0].severity).toBe("warning");
});
test("a channel without lastPropagated is skipped — never deployed, nothing to drift from", async () => {
writeState({});
const fetchImpl = (async () => jsonResponse(200, { releaseId: "acme-r000035" })) as typeof fetch;
const states = await readLiveChannelStates({
workspaceRoot: werkstattRoot,
systemId,
io: createDefaultIO().io,
fetchImpl,
});
expect(states).toHaveLength(0);
expect(liveDriftDiagnostics(states, systemId)).toHaveLength(0);
});
test("a matching live release produces no diagnostics", async () => {
writeState({ main: { releaseId: "acme-r000036" } });
const fetchImpl = (async () => jsonResponse(200, { releaseId: "acme-r000036" })) as typeof fetch;
const states = await readLiveChannelStates({
workspaceRoot: werkstattRoot,
systemId,
io: createDefaultIO().io,
fetchImpl,
});
expect(liveDriftDiagnostics(states, systemId)).toHaveLength(0);
});
test("a 404 identity is LIVE-02, not LIVE-01 — missing identity is a deployment problem", async () => {
writeState({ main: { releaseId: "acme-r000036" } });
const fetchImpl = (async () => jsonResponse(404, {})) as typeof fetch;
const states = await readLiveChannelStates({
workspaceRoot: werkstattRoot,
systemId,
io: createDefaultIO().io,
fetchImpl,
});
const diagnostics = liveDriftDiagnostics(states, systemId);
expect(diagnostics.map((d) => d.ruleId)).toEqual(["LIVE-02"]);
});