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 { createReleaseCandidate } from "./lib/release-candidate.mjs"; const runId = process.env.DADA_TDD_RUN_ID ?? `wp7-01-candidate-${new Date().toISOString().replace(/[^0-9]/g, "")}`; const runDirectory = resolve("artifacts", "tdd", runId); if (existsSync(runDirectory)) throw new Error(`Evidence run already exists: ${runId}`); mkdirSync(runDirectory, { recursive: true }); function run(command, args) { const startedAt = new Date().toISOString(); const executable = process.platform === "win32" ? (process.env.ComSpec ?? "cmd.exe") : command; const actualArgs = process.platform === "win32" ? ["/d", "/s", "/c", [command, ...args].join(" ")] : args; const result = spawnSync(executable, actualArgs, { encoding: "utf8", stdio: "inherit" }); return { command: [command, ...args].join(" "), exit_code: result.status ?? 1, finished_at: new Date().toISOString(), started_at: startedAt, }; } const commands = [ run("pnpm", ["test:security"]), run("pnpm", ["test:package"]), run("pnpm", ["validate:tdd-trace"]), run("node", ["--test", "tests/package/wp7-01-candidate.test.mjs"]), ]; const failed = commands.filter(({ exit_code }) => exit_code !== 0); let candidate; if (failed.length === 0) { const commit = spawnSync("git", ["rev-parse", "HEAD"], { encoding: "utf8" }).stdout.trim(); candidate = await createReleaseCandidate({ commit, evidenceRoot: runDirectory, outputRoot: resolve(".build", runId), }); } writeFileSync(resolve(runDirectory, "commands.json"), `${JSON.stringify({ commands, run_id: runId, schema_version: "1.0" }, null, 2)}\n`); const recordPath = resolve(runDirectory, "release-candidate.json"); const missingEvidence = [ "release-candidate.json", "candidate-package/START-HERE.txt", "candidate-package/package-manifest.json", "candidate-package/package-scan.json", "candidate-package/process-tree.json", ...(candidate ? [`candidate-package/${candidate.record.candidate_package.file_name}`] : []), ].filter((path) => !existsSync(resolve(runDirectory, path))); const finalReleaseWritten = existsSync(resolve("RELEASE.json")); const status = failed.length === 0 && missingEvidence.length === 0 && !finalReleaseWritten ? "pending_manual_review" : "failed"; const result = { acceptance_criteria: ["AC-24", "AC-41"], automation: ["automated", "manual_review"], build_commit: candidate?.record.build_commit ?? null, candidate_status: candidate?.record.status ?? null, final_release_written: finalReleaseWritten, finished_at: new Date().toISOString(), fixed_port: candidate?.record.fixed_port ?? null, manifest: { path: "tasks.manifest.json", sha256: createHash("sha256").update(readFileSync("tasks.manifest.json")).digest("hex").toUpperCase(), }, missing_evidence: missingEvidence, release_gate: ["release:P0-A"], requirements: ["NFR-01", "NFR-09"], run_id: runId, schema_version: "1.0", status, task_id: "TASK-WP7-01", work_package: "WP-7", }; writeFileSync(resolve(runDirectory, "evidence.json"), `${JSON.stringify(result, null, 2)}\n`); console.log(JSON.stringify(result, null, 2)); if (status === "failed") process.exit(1);