zhuyuan-ice-gl-zy001/BRIDGE/tools/zy-evidence-verify.mjs

65 lines
3.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
// zy-evidence-verify.mjs — 证据核查 Agent v1.0(冰朔20260827整改令:证据要被核查真伪)
// 正本:TC-TCS核心卷/TCS-PROTOCOL-ZY001-EVIDENCE-GATE-0001.tcs
// 职责:对单张票据做确定性核查——证据在盘、哈希一致、引文是原文真子串、来源可定位。
// 全过 PASS 才放行提交;任何一项 FAIL 即驳回。纯机械,不猜,不豁免。
import fs from "node:fs";
import path from "node:path";
import crypto from "node:crypto";
const W = "/Volumes/JZAO/铸渊-ICE-GL-ZY001";
const sha256 = (v) => crypto.createHash("sha256").update(v).digest("hex");
export function verifyTicket(t) {
const checks = [];
const add = (id, ok, detail) => checks.push({ id, ok, detail });
add("TICKET_FIELDS", ["ticket","action","claim","source_desc","evidence_file","quote"].every(k => typeof t[k] === "string" && t[k].trim().length > 0),
"四要素+票号非空(动作/主张/来源/证据/引文)");
const abs = t.evidence_file?.startsWith("/") ? t.evidence_file : path.join(W, t.evidence_file);
const inDrive = abs.startsWith(W);
let raw = null;
try { raw = fs.readFileSync(abs, "utf8"); add("EVIDENCE_ON_DRIVE", true, abs); }
catch { add("EVIDENCE_ON_DRIVE", false, `证据文件不存在或不可读: ${abs}`); }
add("EVIDENCE_INSIDE_JZAO", inDrive, inDrive ? "证据在移动硬盘内" : "证据必须在JZAO语言世界内(盘外=不可审计)");
if (raw !== null && t.evidence_sha256) {
add("EVIDENCE_SHA256", sha256(raw) === t.evidence_sha256, `登记哈希与实际${sha256(raw) === t.evidence_sha256 ? "一致" : "不一致(证据被改过或登记错)"}`);
} else if (raw !== null) {
add("EVIDENCE_SHA256", false, "票据缺少 evidence_sha256");
}
if (raw !== null) {
const q = (t.quote || "").trim();
add("QUOTE_IN_SOURCE", q.length >= 8 && raw.includes(q),
q.length < 8 ? "引文过短(<8字符)不足以作为根据" : (raw.includes(q) ? "引文确为证据原文子串" : "引文不在证据文件内(编造引文)"));
}
const sd = t.source_desc || "";
add("SOURCE_LOCATABLE", /(https?:\/\/|瞄点\d{6}|对话|平台|指南|官方|TCS-|ZCODE-DEV)/.test(sd),
sd ? "来源描述含可定位信息(URL/瞄点编号/盘内正本)" : "来源不可定位");
const passed = checks.every(c => c.ok);
return {
agent: "zy-evidence-verify/1.0",
result: passed ? "PASS" : "FAIL",
checks,
at: new Date().toISOString(),
};
}
// CLI: zy-evidence-verify.mjs <ticket.json> → 核查并写回票据,exit 0/1
if (process.argv[1] && process.argv[1].endsWith("zy-evidence-verify.mjs")) {
const p = process.argv[2];
if (!p) { console.error("usage: zy-evidence-verify.mjs <ticket.json>"); process.exit(2); }
let t;
try { t = JSON.parse(fs.readFileSync(p, "utf8")); }
catch (e) { console.error(JSON.stringify({ result: "FAIL", error: "TICKET_READ_FAIL", detail: String(e) })); process.exit(1); }
const audit = verifyTicket(t);
t.audit = audit;
if (audit.result === "PASS") { t.status = "VERIFIED"; } else { t.status = "REJECTED"; }
fs.writeFileSync(p, JSON.stringify(t, null, 1));
console.log(JSON.stringify(audit, null, 1));
process.exit(audit.result === "PASS" ? 0 : 1);
}