Files
moyosapp_beta.0.0.3/scripts/assert-regression.ts
2026-01-15 16:19:14 +02:00

100 lines
2.8 KiB
TypeScript

#!/usr/bin/env tsx
import { promises as fs } from "fs";
type Check =
| {
id: string;
category: string;
description: string;
op: "equalsOrTrue" | "includesAll";
path?: string;
expected?: any;
severity: "blocker" | "major" | "minor";
conditions?: Check[];
}
| {
id: string;
category: string;
description: string;
op: "and" | "or";
severity: "blocker" | "major" | "minor";
conditions: Check[];
};
const getPath = (obj: any, path?: string) => {
if (!path) return undefined;
return path.split(".").reduce((o, k) => (o ? o[k] : undefined), obj);
};
const evalCheck = (facts: any, c: Check): { ok: boolean; reason?: string } => {
switch (c.op) {
case "equalsOrTrue": {
const v = getPath(facts, c.path);
const ok = c.expected === true ? !!v : v === c.expected;
return ok
? { ok }
: {
ok,
reason: `Expected ${c.path} == ${JSON.stringify(
c.expected
)} but got ${JSON.stringify(v)}`,
};
}
case "includesAll": {
const v = String(getPath(facts, c.path) ?? "");
const need = (c.expected ?? []) as string[];
const miss = need.filter((n) => !v.includes(n));
return miss.length === 0
? { ok: true }
: {
ok: false,
reason: `Missing substrings ${miss.join(", ")} in ${c.path}`,
};
}
case "and": {
const results = (c.conditions ?? []).map((x) => evalCheck(facts, x));
const allOk = results.every((r) => r.ok);
return allOk
? { ok: true }
: { ok: false, reason: results.find((r) => !r.ok)?.reason };
}
case "or": {
const results = (c.conditions ?? []).map((x) => evalCheck(facts, x));
const anyOk = results.some((r) => r.ok);
return anyOk
? { ok: true }
: { ok: false, reason: "All OR branches failed" };
}
default:
return { ok: false, reason: "Unknown op" };
}
};
(async () => {
const facts = JSON.parse(
await fs.readFile("conductor/artifacts/facts.json", "utf8")
);
const matrix = JSON.parse(
await fs.readFile("conductor/rules/regression-matrix.json", "utf8")
);
const failures: { id: string; severity: string; reason: string }[] = [];
for (const c of matrix.checks as Check[]) {
const res = evalCheck(facts, c);
if (!res.ok && (c.severity === "blocker" || c.severity === "major")) {
failures.push({
id: c.id,
severity: c.severity,
reason: res.reason ?? "failed",
});
}
}
if (failures.length) {
console.error("⛔ Regression Shield failed:");
for (const f of failures)
console.error(` - [${f.severity}] ${f.id}: ${f.reason}`);
process.exit(2);
}
console.log("✅ Regression Shield passed");
})();