File size: 3,742 Bytes
9c12e58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/**
 * audit-quarantine — Task #254 (B0).
 *
 * 双向扫描:
 *   1. 源码里每个 `QUARANTINE-CONT-XXX` marker → 必须在 KNOWN_CONTAMINATIONS。
 *   2. KNOWN_CONTAMINATIONS 里每条 → 至少在源码出现一次 marker。
 *
 * 任何不一致退出码 1,Test Gate 把它当 hard fail 接入。
 *
 * 防回归点:
 *   - 谁删登记不删源码 → fail(源码 marker orphan)。
 *   - 谁加新假货不登记 → fail(若加了 marker 没在 KNOWN);若不加 marker 也不 audit
 *     就只能靠 code review 抓 — 这是制度的边界,不是 audit 的边界。
 */
import { execFileSync } from "node:child_process";
import { fileURLToPath } from "node:url";
import path from "node:path";

const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");

interface RgMatch {
  file: string;
  line: number;
  text: string;
}

function rgFindMarkers(): RgMatch[] {
  // ripgrep 扫所有 QUARANTINE-CONT-XXX marker。
  // 注意排除 KNOWN_CONTAMINATIONS 自身(quarantine/index.ts)和本 audit 脚本。
  let out = "";
  try {
    out = execFileSync(
      "rg",
      [
        "--no-heading",
        "-n",
        "QUARANTINE-CONT-[0-9]{3}",
        "-g",
        "*.{ts,tsx,js,jsx,mts,cts}",
        "-g",
        "!**/audit-quarantine.ts",
        "-g",
        "!**/quarantine/index.ts",
        "-g",
        "!**/quarantine-enforcement.test.ts",
        "-g",
        "!**/honest-baseline-117.md",
        "artifacts/",
        "lib/",
        "scripts/",
      ],
      { cwd: ROOT, encoding: "utf8" },
    );
  } catch (err: unknown) {
    // ripgrep 退出 1 = no match,我们要把"零 marker"当成 fail 处理(下面统一汇报)。
    const e = err as { status?: number; stdout?: string };
    if (e.status === 1) return [];
    throw err;
  }
  const matches: RgMatch[] = [];
  for (const raw of out.split("\n")) {
    if (!raw.trim()) continue;
    const m = raw.match(/^(.+?):(\d+):(.*)$/);
    if (!m) continue;
    matches.push({ file: m[1], line: Number(m[2]), text: m[3] });
  }
  return matches;
}

function extractContId(text: string): string | null {
  const m = text.match(/QUARANTINE-(CONT-\d{3})/);
  return m ? m[1] : null;
}

async function main(): Promise<void> {
  const { KNOWN_CONTAMINATIONS } = await import(
    "../artifacts/api-server/src/lib/quarantine/index.ts"
  );
  const knownIds = new Set(KNOWN_CONTAMINATIONS.map((c) => c.id));
  const markers = rgFindMarkers();
  const seenIds = new Set<string>();
  const orphanMarkers: string[] = [];

  for (const m of markers) {
    const id = extractContId(m.text);
    if (!id) continue;
    if (!knownIds.has(id)) {
      orphanMarkers.push(`${m.file}:${m.line}  ${id} not in KNOWN_CONTAMINATIONS`);
      continue;
    }
    seenIds.add(id);
  }

  const missing: string[] = [];
  for (const id of knownIds) {
    if (!seenIds.has(id)) missing.push(id);
  }

  console.log(
    `[audit-quarantine] markers found: ${markers.length}, distinct ids: ${seenIds.size}, registry: ${knownIds.size}`,
  );
  let rc = 0;
  if (orphanMarkers.length) {
    console.error("\n[audit-quarantine] ORPHAN MARKERS (in code, not in KNOWN_CONTAMINATIONS):");
    for (const o of orphanMarkers) console.error("  - " + o);
    rc = 1;
  }
  if (missing.length) {
    console.error(
      "\n[audit-quarantine] MISSING MARKERS (registered in KNOWN_CONTAMINATIONS, no `// QUARANTINE-<id>` marker found in source):",
    );
    for (const id of missing) console.error("  - " + id);
    rc = 1;
  }
  if (rc === 0) {
    console.log("[audit-quarantine] ✓ all good (registry ↔ source markers consistent)");
  }
  process.exit(rc);
}

main().catch((err) => {
  console.error("[audit-quarantine] crashed:", err);
  process.exit(2);
});