import crypto from "node:crypto"; import fs from "node:fs"; import path from "node:path"; import { spawnSync } from "node:child_process"; import { fileURLToPath } from "node:url"; const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); const abs = (file) => path.join(root, file); const cachePath = abs("tests/golden/WBV2/context-cache.json"); const read = (file) => fs.readFileSync(abs(file), "utf8"); const digest = (value) => crypto.createHash("sha256").update(value).digest("hex"); const queue = read("docs/EXECUTION_QUEUE.md"); const task = process.argv.includes("--task") ? process.argv[process.argv.indexOf("--task") + 1] : queue.match(/\| 当前任务 \| `([^`]+)` \|/u)?.[1]; if (!task) throw new Error("unable to resolve current WBV2 task"); const parentManifest = queue.match(/\| parent manifest \| `([^`]+)` \|/u)?.[1]; if (!parentManifest) throw new Error("queue parent manifest is missing"); const inputPaths = [ "docs/EXECUTION_QUEUE.md", `docs/tasks/${task}.md`, parentManifest, `tests/golden/${task}/task-context.json`, ]; const inputHash = digest(inputPaths.map((file) => `${file}\0${digest(read(file))}\n`).join("")); let cached = null; try { cached = JSON.parse(fs.readFileSync(cachePath, "utf8")); } catch { /* First use or an interrupted write. */ } if (!process.argv.includes("--force") && cached?.status === "PASS" && cached.task === task && cached.inputHash === inputHash) { process.stdout.write(`wbv2-context-cache-hit task=${task} inputHash=${inputHash}\n`); process.exit(0); } const result = spawnSync(process.execPath, [abs("tools/web/print-task-context.mjs"), "--task", task], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); const check = spawnSync(process.execPath, [abs("tools/web/check-task-context.mjs"), "--task", task], { cwd: root, encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }); if ((result.status ?? 1) !== 0 || (check.status ?? 1) !== 0) { process.stderr.write(`${result.stdout ?? ""}${result.stderr ?? ""}${check.stdout ?? ""}${check.stderr ?? ""}`); process.exit(Math.max(result.status ?? 1, check.status ?? 1)); } fs.mkdirSync(path.dirname(cachePath), { recursive: true }); const payload = { schemaVersion: 1, status: "PASS", task, inputHash, refreshedAt: new Date().toISOString() }; const temporary = `${cachePath}.tmp-${process.pid}`; fs.writeFileSync(temporary, `${JSON.stringify(payload, null, 2)}\n`); fs.renameSync(temporary, cachePath); process.stdout.write(`wbv2-context-cache-refresh task=${task} inputHash=${inputHash}\n`);