feat(corpus): require retrievable visual review evidence

This commit is contained in:
AzuTear
2026-07-11 16:13:02 +02:00
parent 8b9f948c6b
commit 3e2ab61c97
14 changed files with 325 additions and 73 deletions
+27 -2
View File
@@ -60,12 +60,33 @@ function stableId(value) {
.slice(0, 80) || "review-case";
}
function safeProvenanceValue(value, fallback = "unknown") {
const text = typeof value === "string" ? value.trim() : "";
if (!text || text.length > 200 || /[\r\n]/.test(text)) return fallback;
if (path.isAbsolute(text) || /[A-Za-z]:[\\/]/.test(text) || text.startsWith("\\\\")) return fallback;
return text;
}
function visualEvidenceNote(candidate) {
const status = candidate?.visualEvidence?.status === "available" ? "available" : "unavailable";
const parts = [`visualEvidence=${status}`];
const captureId = safeProvenanceValue(candidate?.captureId, "");
const capturedAt = safeProvenanceValue(candidate?.capturedAt, "");
if (captureId) parts.push(`captureId=${captureId}`);
if (capturedAt) parts.push(`capturedAt=${capturedAt}`);
return parts.join(" | ");
}
function objectLiteral(value, indent = 2) {
return JSON.stringify(value, null, indent).replace(/"([A-Za-z_$][0-9A-Za-z_$]*)":/g, "$1:");
}
function snippetFor(candidate, expect) {
const id = stableId(argValue("id", `confirmed-${candidate.id}`));
const reason = safeProvenanceValue(candidate.reason, "review-sample");
const savedAt = safeProvenanceValue(candidate.savedAt, "unknown");
const resolution = safeProvenanceValue(candidate.resolution, "");
const sourceCandidate = stableId(candidate.id);
const entry = {
id,
confirmed: true,
@@ -73,8 +94,8 @@ function snippetFor(candidate, expect) {
expect,
meta: {
source: "review-sample",
resolution: candidate.resolution || undefined,
note: `${candidate.reason || "review-sample"} | savedAt=${candidate.savedAt || "unknown"} | sourceCandidate=${candidate.id}`,
resolution: resolution || undefined,
note: `${reason} | savedAt=${savedAt} | sourceCandidate=${sourceCandidate} | ${visualEvidenceNote(candidate)}`,
},
};
return `${objectLiteral(entry, 2)},\n`;
@@ -90,6 +111,9 @@ function main() {
if (!candidateId) throw new Error("Missing candidate id. Pass --candidate=<id>.");
const outputPath = path.resolve(argValue("out", path.join(process.cwd(), "outputs", "review-eval-candidates", `${stableId(candidateId)}.confirmed.ts`)));
const candidate = loadCandidate(inputPath, candidateId);
if (candidate?.visualEvidence?.status !== "available") {
throw new Error("Candidate has no retrievable visual evidence. Re-export after retaining a local PNG before preparing a confirmed corpus case.");
}
const expect = parseExpectedFields();
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
const snippet = snippetFor(candidate, expect);
@@ -106,4 +130,5 @@ module.exports = {
parseExpectedFields,
snippetFor,
stableId,
visualEvidenceNote,
};