Files
ThothII/harness/.pi/extensions/gate/__tests__/artifact_contracts.test.js
T

174 lines
6.4 KiB
JavaScript

// Soft-validators for the v2 artifact payloads (contracts.md A/B/C). Pure, no I/O.
// A payload without schema_version===2 is NOT an error -- it's legacy, and the caller
// falls back to the current (pre-v2) rendering path.
const test = require("node:test");
const assert = require("node:assert");
const {
validateCtePlanV2,
validateCteResultThin,
validatePhaseSummaryV2,
} = require("../core/artifact-contracts.js");
// --- validateCtePlanV2 (payload A) ------------------------------------------------
test("validateCtePlanV2: legacy (no schema_version) is ok:true, legacy:true", () => {
const out = validateCtePlanV2({ some: "legacy shape" });
assert.deepEqual(out, { ok: true, legacy: true });
});
test("validateCtePlanV2: legacy when data is a plain string (markdown)", () => {
const out = validateCtePlanV2("### Piano CTE\n1. foo");
assert.deepEqual(out, { ok: true, legacy: true });
});
test("validateCtePlanV2: valid v2 payload", () => {
const out = validateCtePlanV2({
schema_version: 2,
question: "domanda",
strategy: "razionale",
ctes: [
{ name: "base_pazienti", purpose: "p", rationale: "r", depends_on: [], tables: [], keys: [], filters: [], output_columns: [] },
{ name: "eventi", purpose: "p2", rationale: "r2", depends_on: ["base_pazienti"], tables: [], keys: [], filters: [], output_columns: [] },
],
});
assert.equal(out.ok, true);
assert.ok(!out.errors || out.errors.length === 0);
});
test("validateCtePlanV2: rejects missing ctes array", () => {
const out = validateCtePlanV2({ schema_version: 2, question: "q", strategy: "s" });
assert.equal(out.ok, false);
assert.ok(out.errors.some((e) => /ctes/.test(e)));
});
test("validateCtePlanV2: rejects a CTE missing name", () => {
const out = validateCtePlanV2({
schema_version: 2, question: "q", strategy: "s",
ctes: [{ purpose: "p" }],
});
assert.equal(out.ok, false);
assert.ok(out.errors.some((e) => /ctes\[0\].*name/.test(e)));
});
test("validateCtePlanV2: rejects depends_on referencing an unknown/forward CTE", () => {
const out = validateCtePlanV2({
schema_version: 2, question: "q", strategy: "s",
ctes: [
{ name: "a", depends_on: ["b"] }, // b does not precede a
{ name: "b", depends_on: [] },
],
});
assert.equal(out.ok, false);
assert.ok(out.errors.some((e) => /depends_on/.test(e) && /'b'/.test(e)));
});
test("validateCtePlanV2: depends_on referencing an earlier CTE is fine", () => {
const out = validateCtePlanV2({
schema_version: 2, question: "q", strategy: "s",
ctes: [
{ name: "a", depends_on: [] },
{ name: "b", depends_on: ["a"] },
],
});
assert.equal(out.ok, true);
});
// --- validateCteResultThin (payload B, model side is THIN) ------------------------
test("validateCteResultThin: legacy (string/markdown) is ok:true, legacy:true", () => {
assert.deepEqual(validateCteResultThin("**CTE risultato**: ok"), { ok: true, legacy: true });
assert.deepEqual(validateCteResultThin({ some: "legacy" }), { ok: true, legacy: true });
});
test("validateCteResultThin: valid thin v2 payload (all fields optional)", () => {
const out = validateCteResultThin({ schema_version: 2 });
assert.equal(out.ok, true);
});
test("validateCteResultThin: valid thin v2 payload with purpose/rationale/note", () => {
const out = validateCteResultThin({
schema_version: 2, purpose: "seleziona pazienti", rationale: "base per la catena", note: "ok",
});
assert.equal(out.ok, true);
});
test("validateCteResultThin: rejects non-string purpose/rationale/note", () => {
const out = validateCteResultThin({ schema_version: 2, purpose: 42 });
assert.equal(out.ok, false);
assert.ok(out.errors.some((e) => /purpose/.test(e)));
});
test("validateCteResultThin: permissive on extra fields (e.g. a model that also sends sql) -- guidance against this lives in SKILL.md, not the validator", () => {
const out = validateCteResultThin({ schema_version: 2, sql: "WITH a AS (SELECT 1)" });
assert.equal(out.ok, true);
});
// --- validatePhaseSummaryV2 (payload C) -------------------------------------------
test("validatePhaseSummaryV2: legacy (no schema_version) is ok:true, legacy:true", () => {
assert.deepEqual(validatePhaseSummaryV2({ recap: "legacy text" }), { ok: true, legacy: true });
assert.deepEqual(validatePhaseSummaryV2("legacy markdown"), { ok: true, legacy: true });
});
test("validatePhaseSummaryV2: valid minimal v2 payload", () => {
const out = validatePhaseSummaryV2({ schema_version: 2, summary: "riepilogo" });
assert.equal(out.ok, true);
});
test("validatePhaseSummaryV2: valid full v2 payload", () => {
const out = validatePhaseSummaryV2({
schema_version: 2,
summary: "riepilogo",
checks: [{ label: "schema valido", status: "ok" }],
sections: [{ title: "Criteri", items: [{ label: "flag attivo", table: "t", column: "c", value: "TRUE", kind: "filter" }] }],
tables: [{ name: "t", role: "promoted", columns: [{ name: "c" }] }],
open_questions: [],
});
assert.equal(out.ok, true);
});
test("validatePhaseSummaryV2: rejects missing summary", () => {
const out = validatePhaseSummaryV2({ schema_version: 2 });
assert.equal(out.ok, false);
assert.ok(out.errors.some((e) => /summary/.test(e)));
});
test("validatePhaseSummaryV2: rejects a check with an invalid status", () => {
const out = validatePhaseSummaryV2({
schema_version: 2, summary: "s",
checks: [{ label: "x", status: "maybe" }],
});
assert.equal(out.ok, false);
assert.ok(out.errors.some((e) => /checks\[0\].*status/.test(e)));
});
test("validatePhaseSummaryV2: rejects a section missing title or items", () => {
const out = validatePhaseSummaryV2({
schema_version: 2, summary: "s",
sections: [{ items: [] }],
});
assert.equal(out.ok, false);
assert.ok(out.errors.some((e) => /sections\[0\].*title/.test(e)));
});
test("validatePhaseSummaryV2: rejects structured open_questions instead of crashing the UI", () => {
const out = validatePhaseSummaryV2({
schema_version: 2,
summary: "s",
open_questions: [
{
label: "pazienti_finale restituisce 0 righe",
question: "Verificare se i filtri sono troppo restrittivi",
},
],
});
assert.equal(out.ok, false);
assert.ok(out.errors.some((error) => /open_questions\[0\]/.test(error)));
});
test("validatePhaseSummaryV2: permissive on extra unknown fields", () => {
const out = validatePhaseSummaryV2({ schema_version: 2, summary: "s", extra_field_from_model: "whatever" });
assert.equal(out.ok, true);
});