// @vitest-environment node import { readFileSync } from "node:fs"; import { expect, it } from "vitest"; // 배포 표기와 재현 명령을 함께 고정한다. 과거 인수 기록은 검사·수정하지 않는다. it("0.2.5 버전을 package·lock·UI·index·문서에 일치시킨다", () => { const pkg = JSON.parse(readFileSync("package.json", "utf8")); const lock = JSON.parse(readFileSync("package-lock.json", "utf8")); expect.soft(pkg.version).toBe("0.2.5"); expect.soft(lock.version).toBe("0.2.5"); expect.soft(lock.packages[""].version).toBe("0.2.5"); for (const path of [ "src/App.tsx", "index.html", "README.md", "LICENSE", "docs/AUDIO_PROVENANCE.md", ]) { expect.soft(readFileSync(path, "utf8"), path).toContain("0.2.5"); } }); it("고정 venv 생성 명령과 provider·도구·출력물 권리의 경계를 문서화한다", () => { const pkg = JSON.parse(readFileSync("package.json", "utf8")); expect .soft(pkg.scripts["audio:generate"]) .toBe(".venv-audio/bin/python scripts/generate_audio.py"); for (const path of ["README.md", "docs/AUDIO_PROVENANCE.md"]) { const doc = readFileSync(path, "utf8"); expect.soft(doc, path).toContain("requirements-audio.txt"); expect.soft(doc, path).toContain("ko-KR-HyunsuMultilingualNeural"); expect.soft(doc, path).toContain("7.3.1"); expect.soft(doc, path).not.toMatch(/espeak|포먼트/i); } const provenance = readFileSync("docs/AUDIO_PROVENANCE.md", "utf8"); expect .soft(provenance) .toContain("https://www.microsoft.com/en-us/servicesagreement"); expect.soft(provenance).toContain("LGPL"); expect.soft(provenance).toContain("독점 권리를 주장하지 않는다"); expect .soft(readFileSync("LICENSE", "utf8")) .toContain("does not claim exclusive rights to generated speech"); }); // 현재 문서는 같은 릴리스를 설명하고 변경 이력은 이전 근거를 보존해야 한다. it("현재 문서·manifest·CHANGELOG는 0.2.5 동작과 역사 보존을 설명한다", () => { for (const path of [ "docs/ARCHITECTURE.md", "docs/DEPLOYMENT.md", "docs/WORDS.md", "public/audio/manifest.json", "src/audio/assets.ts", ]) expect.soft(readFileSync(path, "utf8"), path).toContain("0.2.5"); const history = readFileSync("CHANGELOG.md", "utf8"); for (const version of ["0.2.5", "0.2.3", "0.1.1", "0.1.0"]) expect(history).toContain(version); for (const change of [ "SNR", "3문항", "중도 종료", "CC BY-SA", "Chrome", "회귀", ]) expect(history).toContain(change); }); it("README는 현재 리뷰 증거 경로와 정확한 라운드 보너스를 안내한다", () => { const doc = readFileSync("README.md", "utf8"); expect.soft(doc).toContain(".agent/evidence-v0.2.5/"); expect.soft(doc).toContain("문항별 최대 20점, 라운드 합계 최대 30점"); });