import { spawnSync } from "node:child_process"; import { createHash } from "node:crypto"; import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"; import { resolve } from "node:path"; import { validateTddTrace } from "./lib/tdd-trace.mjs"; import { buildWp706PrefreezeReport, REQUIRED_UPSTREAM } from "./lib/wp7-06-prefreeze.mjs"; const runId = process.env.DADA_TDD_RUN_ID ?? `wp7-06-prefreeze-${new Date().toISOString().replace(/[^0-9]/g, "")}`; const runDirectory = resolve("artifacts", "tdd", runId); const caseDirectory = resolve(runDirectory, "cases", "TDD-WP7-AC-001-trace-structure"); if (existsSync(runDirectory)) throw new Error(`Evidence run already exists: ${runId}`); mkdirSync(caseDirectory, { recursive: true }); function writeJson(path, value) { writeFileSync(path, `${JSON.stringify(value, null, 2)}\n`); } function git(args) { const result = spawnSync("git", args, { encoding: "utf8", timeout: 60_000 }); if ((result.status ?? 1) !== 0) throw new Error(`WP7_06_GIT_COMMAND_FAILED:${args[0]}`); return result.stdout.trim(); } function runCommand(name, command) { const startedAt = new Date().toISOString(); const result = spawnSync(process.env.ComSpec ?? "cmd.exe", ["/d", "/s", "/c", command], { encoding: "utf8", env: process.env, maxBuffer: 64 * 1024 * 1024, }); if (result.stdout) process.stdout.write(result.stdout); if (result.stderr) process.stderr.write(result.stderr); return { command, exit_code: result.status ?? 1, finished_at: new Date().toISOString(), name, started_at: startedAt, }; } const commands = [ runCommand("prefreeze-unit", "node --test tests/package/wp7-06-prefreeze.test.mjs"), runCommand("tdd-trace", "pnpm validate:tdd-trace"), ]; if (commands.some((command) => command.exit_code !== 0)) { writeJson(resolve(caseDirectory, "commands.json"), { commands, run_id: runId, schema_version: "1.0" }); process.exit(1); } const trace = validateTddTrace(); const currentCommit = git(["rev-parse", "HEAD"]); const remoteLines = git(["ls-remote", "--heads", "origin", "codex/wp7-01", "codex/wp7-02", "codex/wp7-03", "codex/wp7-04", "codex/wp7-05"]) .split(/\r?\n/) .filter(Boolean); const remoteHeads = Object.fromEntries(remoteLines.map((line) => { const [head, reference] = line.split(/\s+/); return [reference.replace("refs/heads/", ""), head]; })); const upstream = Object.fromEntries(Object.entries(REQUIRED_UPSTREAM).map(([taskId, status]) => { const branch = taskId.replace("TASK-", "codex/").toLowerCase(); const head = remoteHeads[branch]; const ancestry = spawnSync("git", ["merge-base", "--is-ancestor", head ?? "missing", "HEAD"], { encoding: "utf8", timeout: 30_000 }); return [taskId, { branch, head, merged: ancestry.status === 0, status }]; })); const report = buildWp706PrefreezeReport({ currentCommit, releaseExists: existsSync(resolve("RELEASE.json")), trace, upstream, }); const result = { acceptance_criteria: Array.from({ length: 56 }, (_, index) => index + 1) .filter((number) => ![8, 26, 37, 54].includes(number)) .map((number) => `AC-${String(number).padStart(2, "0")}`), automation: ["automated", "manual_review"], commit: currentCommit, evidence_refs: ["commands.json", "trace-summary.json", "upstream-lineage.json", "deferred-external.json"], finished_at: new Date().toISOString(), manifest: { path: "tasks.manifest.json", sha256: createHash("sha256").update(readFileSync("tasks.manifest.json")).digest("hex").toUpperCase(), }, missing_evidence: [], release_gate: ["release:P0-A"], requirements: ["NFR-05"], run_id: runId, schema_version: "1.0", status: report.status, task_id: "TASK-WP7-06", test_id: "TDD-WP7-AC-001-trace-structure", work_package: "WP-7", }; writeJson(resolve(caseDirectory, "commands.json"), { commands, run_id: runId, schema_version: "1.0" }); writeJson(resolve(caseDirectory, "trace-summary.json"), { status: trace.status, summary: trace.summary, schema_version: "1.0" }); writeJson(resolve(caseDirectory, "upstream-lineage.json"), { current_commit: currentCommit, tasks: report.upstream, schema_version: "1.0" }); writeJson(resolve(caseDirectory, "deferred-external.json"), { policy: "product_owner_first_version_nonblocking", tasks: report.deferred_external_tasks, treated_as_real_provider_pass: false, schema_version: "1.0", }); writeJson(resolve(caseDirectory, "result.json"), result); writeJson(resolve(runDirectory, "evidence.json"), { cases: [{ missing_evidence: [], status: result.status, test_id: result.test_id }], run_id: runId, status: result.status, schema_version: "1.0" }); console.log(JSON.stringify({ deferred_external_tasks: report.deferred_external_tasks, next_task: report.next_task, run_id: runId, status: report.status }, null, 2));