export interface EvidenceRow { criterion: string; artifact: string; notes?: string; } /** Render an evidence index markdown table. */ export function formatEvidenceIndex(rows: EvidenceRow[]): string { const lines: string[] = [ "| Criterion | Artifact | Notes |", "|-----------|----------|-------|", ]; for (const r of rows) { const notes = (r.notes ?? "").replace(/\|/g, "\\|"); const criterion = r.criterion.replace(/\|/g, "\\|"); const artifact = r.artifact.replace(/\|/g, "\\|"); lines.push(`| ${criterion} | ${artifact} | ${notes} |`); } lines.push(""); return lines.join("\n"); } /** Parse an evidence index markdown table into rows (best-effort). */ export function parseEvidenceIndex(md: string): EvidenceRow[] { const rows: EvidenceRow[] = []; for (const line of md.split("\n")) { const trimmed = line.trim(); if (!trimmed.startsWith("|")) continue; if (/^\|\s*-+/.test(trimmed)) continue; const parts = trimmed .replace(/^\|/, "") .replace(/\|$/, "") .split("|") .map((c) => c.trim()); if (parts.length < 2) continue; const head = parts[0]!.toLowerCase(); if (head === "criterion" || head.startsWith("---")) continue; const row: EvidenceRow = { criterion: parts[0]!, artifact: parts[1]!, }; if (parts[2]) row.notes = parts[2]; rows.push(row); } return rows; }