import fs from "node:fs"; import { spawnSync } from "node:child_process"; import { evidencePath, expectedEvidenceIdentity, root, sha256 } from "./v1-acceptance-lib.mjs"; const identity = expectedEvidenceIdentity(); const previous = JSON.parse(fs.readFileSync(evidencePath, "utf8")); const failedTokens = new Set(previous.results.filter((item) => item.exitCode !== 0).map((item) => item.token)); if (failedTokens.size === 0) throw new Error("V1 acceptance evidence has no failed entries to rerun"); const replacements = new Map(); for (const entry of identity.plan.entries.filter((item) => failedTokens.has(item.token))) { const started = Date.now(); process.stdout.write(`[focused] ${entry.token}\n`); const result = spawnSync("npm", ["--prefix", "web", "run", entry.script, ...entry.args], { cwd: root, encoding: "utf8", env: { ...process.env, FORCE_COLOR: "0", NO_COLOR: "1", WEB_TEST_PORT: String(6200 + replacements.size) }, maxBuffer: 32 * 1024 * 1024, }); const output = `${result.stdout ?? ""}\n${result.stderr ?? ""}`.trim(); const storedOutput = output.slice(-4096) || `${entry.token} produced no output`; replacements.set(entry.token, { token: entry.token, familyIds: entry.familyIds, command: entry.command, exitCode: result.status ?? 1, durationMs: Date.now() - started, outputSha256: sha256(storedOutput), output: storedOutput, }); process.stdout.write(` exit=${result.status ?? 1} durationMs=${Date.now() - started}\n`); } const results = identity.plan.entries.map((entry) => replacements.get(entry.token) ?? previous.results.find((item) => item.token === entry.token)); const manifest = { ...previous, sourceSha256: identity.ledgerSha256, packageSha256: identity.packageSha256, toolSourceSha256: identity.toolSourceSha256, generatedAt: new Date().toISOString(), environment: { ...previous.environment, blenderBin: process.env.BLENDER_BIN ? "BLENDER_BIN" : previous.environment.blenderBin, blenderArchiveSha256: process.env.BLENDER_ARCHIVE_SHA256 ?? previous.environment.blenderArchiveSha256, }, summary: { families: identity.plan.familyCount, declarations: identity.plan.declarationCount, unique: identity.plan.uniqueCount, passed: results.filter((item) => item.exitCode === 0).length, failed: results.filter((item) => item.exitCode !== 0).length, }, results, }; fs.writeFileSync(evidencePath, `${JSON.stringify(manifest, null, 2)}\n`); process.stdout.write(`v1-acceptance-focused-complete rerun=${replacements.size} passed=${manifest.summary.passed} failed=${manifest.summary.failed}\n`); if (manifest.summary.failed > 0) process.exitCode = 1;