import * as fs from "node:fs"; import * as os from "node:os"; import * as path from "node:path"; import { afterEach, describe, expect, it } from "vitest"; import { reconcileRsi, verifyCanaryProof } from "./rsi-reconcile.js"; const roots: string[] = []; afterEach(() => { for (const root of roots.splice(0)) fs.rmSync(root, { recursive: true, force: true }); }); function tmpFile(): string { const root = fs.mkdtempSync(path.join(os.tmpdir(), "fable-rsi-reconcile-")); roots.push(root); return path.join(root, "receipt.json"); } function runner(overrides: Record = {}) { return (_command: string, args: string[]) => { const script = args.at(-1) ?? ""; const hit = Object.entries(overrides).find(([needle]) => script.includes(needle))?.[1]; if (hit) return { status: hit.status, stdout: hit.stdout, stderr: hit.stderr ?? "" }; if (script.includes("skill_health.py|rsi-diagnosis")) return { status: 0, stdout: "0 */6 * * * docker cp /tmp/skill_health.py hermes:/tmp/skill_health.py\n", stderr: "" }; if (script.includes("test -f /tmp/skill_health.py")) return { status: 0, stdout: "present\n", stderr: "" }; if (script.includes("tail -160")) return { status: 0, stdout: "RSI: 65/65 (100%)\nAll healthy — ZTE idle\n", stderr: "" }; if (script.includes("systemctl is-active")) return { status: 0, stdout: "active\n", stderr: "" }; if (script.includes("/deploy")) return { status: 0, stdout: "present\n", stderr: "" }; return { status: 1, stdout: "", stderr: "unexpected" }; }; } describe("rsi reconcile", () => { it("marks healthy but autopatch unproven when all health checks pass", () => { const receipt = reconcileRsi({ host: "example", runner: runner(), now: new Date("2026-06-18T00:00:00Z") }); expect(receipt.facts.cron_present).toBe(true); expect(receipt.facts.latest_score).toBe("65/65 (100%)"); expect(receipt.decision).toBe("healthy_but_autopatch_unproven"); }); it("marks healthy when auto-patch evidence exists", () => { const receipt = reconcileRsi({ host: "example", runner: runner({ "tail -160": { status: 0, stdout: "RSI: 65/65 (100%)\nauto-patching 1 degraded skills\nAll patched successfully\n" } }) }); expect(receipt.facts.auto_patch_proven).toBe(true); expect(receipt.decision).toBe("healthy"); }); it("marks healthy when a fresh canary proof receipt exists", () => { const proof = tmpFile(); fs.writeFileSync(proof, [ "rsi_canary: degraded", "STATUS_BEFORE:1", "auto-patching 1 degraded skills", "All patched successfully", "rsi_canary: recovered", "STATUS_PATCH:0", "STATUS_AFTER:0", ].join("\n")); expect(verifyCanaryProof(proof)).toBe(true); const receipt = reconcileRsi({ host: "example", canaryProof: proof, runner: runner() }); expect(receipt.facts.auto_patch_proven).toBe(true); expect(receipt.facts.canary_proof).toBe(proof); expect(receipt.decision).toBe("healthy"); }); it("keeps healthy when only cron naming drifts", () => { const receipt = reconcileRsi({ host: "example", runner: runner({ "skill_health.py|rsi-diagnosis": { status: 1, stdout: "" } }) }); expect(receipt.facts.cron_present).toBe(false); expect(receipt.decision).toBe("healthy_but_autopatch_unproven"); }); it("marks degraded when live skill health is missing", () => { const receipt = reconcileRsi({ host: "example", runner: runner({ "test -f /tmp/skill_health.py": { status: 1, stdout: "" } }) }); expect(receipt.facts.skill_health_present).toBe(false); expect(receipt.decision).toBe("degraded"); }); it("writes a receipt", () => { const out = tmpFile(); reconcileRsi({ host: "example", out, runner: runner() }); expect(fs.readFileSync(out, "utf-8")).toContain("healthy_but_autopatch_unproven"); }); });