/** * 「声明了 `GRAPH_RUNS_DIR` 覆盖的模块,必须真的用上它」(27-P3C 验收 12c / §九.4quater)。 * * 为什么需要这条元测试:`goal-contract.js` 里曾有一行 * `/** run 目录根的覆盖,与 graph-engine.RUNS_ROOT 是同一个变量(测试隔离在用) *\/` * `const RUNS_ROOT = process.env.GRAPH_RUNS_DIR || null;` * 注释承诺「测试隔离在用」,全文件却**零引用** —— `resolveRunDir` 照旧返回仓库 * `data/companies/…`。后果不是少个功能,是**两个方向的静默错位**: * · 测试设了 env,写侧落进临时目录、读侧还去仓库里找 → 读到 null, * `describeTask` 静默退回兜底文案「执行图节点任务」,agent 不知道要干什么却照样烧预算; * · 反过来跑测试时往真实 `data/companies/` 里堆目录,一次跑一堆残留。 * 两种都不报错。这正是本仓库数到第五次以上的「实现在、零调用方」换个方向再来一次: * 常量在、注释在,唯独没有调用方。 * * 断言的是**形状不变式**而不是某个具体文件的行为:凡是把 `process.env.GRAPH_RUNS_DIR` * 绑到一个标识符上的地方,那个标识符都必须在代码里(不是注释里)至少被用一次。 * 直接内联 `process.env.GRAPH_RUNS_DIR` 的写法天然不在射程内 —— 那种写法本身就是使用。 * * 形状照抄 `agents-root-single-holder.test.js`,含它那条「样本非空」前置断言: * 扫不到文件时这类测试会静默全绿,那正是它自己变成「零调用方」的方式。 */ const fs = require('fs'); const path = require('path'); const REPO_ROOT = path.resolve(__dirname, '../../..'); /** 只扫真正会被执行的源码,跳过依赖、构建产物与测试自身(测试里设 env 是正当用法) */ const SCAN_DIRS = ['server', 'packages', 'scripts']; const SKIP_DIR = /(^|\/)(node_modules|dist|\.git|coverage)(\/|$)/; const SKIP_FILE = /\.test\.js$/; /** `const X = process.env.GRAPH_RUNS_DIR …`(含函数内的局部变量,形态一样、病也一样) */ const DECL = /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*process\.env\.GRAPH_RUNS_DIR\b/g; /** * 去掉注释再数使用次数 —— 这条元测试要挡的那个 bug,现场恰恰是「注释里写着在用、 * 代码里没有」。不剥注释的话它会被自己的注释洗成绿色。 */ function stripComments(src) { return src.replace(/\/\*[\s\S]*?\*\//g, ' ').replace(/(^|[^:])\/\/[^\n]*/g, '$1'); } function walk(dir, out = []) { let entries; try { entries = fs.readdirSync(dir, { withFileTypes: true }); } catch { return out; // 目录不存在(如仓库裁剪过)就跳过,不让本测试成为噪声源 } for (const e of entries) { const full = path.join(dir, e.name); if (SKIP_DIR.test(full)) continue; if (e.isDirectory()) walk(full, out); else if (e.name.endsWith('.js') && !SKIP_FILE.test(e.name)) out.push(full); } return out; } /** 一个文件里所有「绑了 GRAPH_RUNS_DIR 的标识符」及其行号 */ function declarations(code, rawSrc) { const found = []; for (const m of code.matchAll(DECL)) { const name = m[1]; // 行号按原文件算,报出来才能直接跳过去 const idx = rawSrc.indexOf(m[0]); found.push({ name, line: idx < 0 ? 0 : rawSrc.slice(0, idx).split('\n').length }); } return found; } describe('GRAPH_RUNS_DIR 的覆盖不许只声明不使用(27-P3C 验收 12c)', () => { const files = SCAN_DIRS.flatMap((d) => walk(path.join(REPO_ROOT, d))); const decls = files.flatMap((f) => { const raw = fs.readFileSync(f, 'utf-8'); if (!raw.includes('GRAPH_RUNS_DIR')) return []; const code = stripComments(raw); return declarations(code, raw).map((d) => ({ ...d, file: f, code })); }); it('扫描样本非空 —— 防止路径或正则写错时本测试退化成永远通过', () => { // 没有这两条,walk() 的容错与 DECL 的任何笔误都会表现为全绿。 expect(files.length).toBeGreaterThan(100); // 至少 company-paths / goal-contract / routes-company 三处 `const runsRoot = process.env…` // 必须被扫到(graph-engine 与 graph-run-sse 的那两处模块级快照已按缺陷 F8 改成 // 「每次调用时读」的函数,直接内联 env、不再绑标识符,天然不在本测试射程内) expect(decls.length).toBeGreaterThanOrEqual(2); }); it('每个绑定都在代码里被真正用到(注释里提到不算)', () => { const offenders = []; for (const d of decls) { // 出现次数 > 1 = 除了声明本身还有别的地方在读它 const uses = (d.code.match(new RegExp(`\\b${d.name}\\b`, 'g')) || []).length; if (uses <= 1) { offenders.push( `${path.relative(REPO_ROOT, d.file)}:${d.line} → ${d.name} 绑了 GRAPH_RUNS_DIR 却零使用` ); } } expect(offenders).toEqual([]); }); });