#!/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 → 核查并写回票据,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 "); 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); }