import { CAPABILITY_IDS } from "@umt/contracts"; // 汇报格式的机器核对(AG-5 评测用):fake 模型评测与真实模型评测共用。 // 只查能机械判断的项;"结论在第一句"按开头的套话与是否含状态词近似判断。 export interface ReportLintIssue { rule: | "too_long" | "uuid" | "hash" | "raw_bytes" | "iso_time" | "internal_field" | "capability_id" | "heading" | "no_conclusion_first" | "asks_user_for_id" | "lecture"; detail: string; } export interface ReportLintOptions { /** 最多几行(非空行);缺省 8 */ maxLines?: number; } const UUID = /\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/i; const HASH = /\b[0-9a-f]{40}(?:[0-9a-f]{24})?\b/i; /** 7 位以上的裸数字(原始字节数、原始计数);年份、日期、带千分位的不算 */ const RAW_NUMBER = /(? l.trim()) .filter((l) => l !== "" && !/^\|?\s*:?-{3,}/.test(l)); if (lines.length > maxLines) issues.push({ rule: "too_long", detail: `${lines.length} 行,超过 ${maxLines} 行` }); const find = (re: RegExp) => text.match(re)?.[0]; const hit = (rule: ReportLintIssue["rule"], re: RegExp) => { const m = find(re); if (m) issues.push({ rule, detail: m }); }; hit("uuid", UUID); hit("hash", HASH); hit("raw_bytes", RAW_NUMBER); hit("iso_time", ISO_TIME); hit("internal_field", INTERNAL_WORDS); const snake = find(SNAKE); if (snake) issues.push({ rule: "internal_field", detail: snake }); const camel = text.match(new RegExp(CAMEL, "g"))?.find((w) => !ALLOWED_TOKENS.has(w)); if (camel) issues.push({ rule: "internal_field", detail: camel }); const cap = CAPABILITY_IDS.find((id) => text.includes(id)); if (cap) issues.push({ rule: "capability_id", detail: cap }); if (/^#{1,6} /m.test(text)) issues.push({ rule: "heading", detail: "用了 Markdown 标题" }); const first = lines[0] ?? ""; if (!first || WEAK_OPENERS.test(first)) issues.push({ rule: "no_conclusion_first", detail: first.slice(0, 40) }); hit("asks_user_for_id", ASK_ID); hit("lecture", LECTURE); return issues; }