Files
citation-engine/src/shared/evidence-link.test.ts
tegwick 78085e1eb3 Extract engine from citation-evidence umbrella (CENG-WP-0001)
Bootstrap @citation-evidence/engine as a standalone TypeScript package
with shared types and engine services copied from the umbrella MVP.
All 89 tests pass with lint and typecheck clean.
2026-06-22 18:02:05 +02:00

63 lines
2.3 KiB
TypeScript

/**
* Conformance test: the runtime enum lists in `evidence-link.ts` must
* match the lists in `wiki/SharedContracts.md` §2.4 and §2.5 exactly.
*
* If you intentionally change an enum, update both the doc and the
* runtime list together — this test will tell you which one you forgot.
*/
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { describe, expect, it } from "vitest";
import {
EVIDENCE_LINK_STATUS_VALUES,
EVIDENCE_RELATION_VALUES,
} from "./evidence-link";
const HERE = fileURLToPath(new URL(".", import.meta.url));
const CONTRACTS_PATH = resolve(HERE, "../../wiki/SharedContracts.md");
function extractFencedListAfterHeading(markdown: string, heading: string): string[] {
const headingIndex = markdown.indexOf(heading);
if (headingIndex === -1) {
throw new Error(`Could not find heading "${heading}" in SharedContracts.md`);
}
const after = markdown.slice(headingIndex + heading.length);
const fenceOpen = after.indexOf("```");
if (fenceOpen === -1) throw new Error(`No fenced block after "${heading}"`);
const bodyStart = after.indexOf("\n", fenceOpen) + 1;
const fenceClose = after.indexOf("```", bodyStart);
if (fenceClose === -1) throw new Error(`Unterminated fenced block after "${heading}"`);
const body = after.slice(bodyStart, fenceClose);
return body
.split("\n")
.map((line) => line.trim())
.filter((line) => line.length > 0)
// Strip trailing " — explanatory note" if present (none in §2.4/§2.5 today,
// but §2.1/§2.2 use that style — being defensive keeps the helper reusable).
.map((line) => line.split(/\s+[—-]\s+/)[0]!.trim());
}
describe("EvidenceLink enum conformance with SharedContracts.md", () => {
const markdown = readFileSync(CONTRACTS_PATH, "utf8");
it("§2.4 EvidenceLink.status matches EVIDENCE_LINK_STATUS_VALUES", () => {
const docValues = extractFencedListAfterHeading(
markdown,
"### 2.4 `EvidenceLink.status` (per target)",
);
expect(docValues).toEqual([...EVIDENCE_LINK_STATUS_VALUES]);
});
it("§2.5 EvidenceLink.relation matches EVIDENCE_RELATION_VALUES", () => {
const docValues = extractFencedListAfterHeading(
markdown,
"### 2.5 `EvidenceLink.relation`",
);
expect(docValues).toEqual([...EVIDENCE_RELATION_VALUES]);
});
});