---
pr: 187
title: fix(draw-image): per-process output TMP in e2e.test.ts beforeAll race
---

## Что сделано
- `e2e.test.ts` переведён с общего output-каталога `/tmp/draw-image-e2e` на per-process: `TMP = path.join(os.tmpdir(), \`draw-image-e2e-\${process.pid}\`)`.
- Добавлен `import os from "node:os"`.
- Добавлен `afterAll` с `rmSync(TMP, { recursive: true, force: true })` (импорт `afterAll` уже присутствовал в vitest-импорте, но блок отсутствовал — критерий приемки требует "no leftover").
- Добавлен handoff + ADR-082.

## Почему
`tests/e2e.test.ts` использовал общий `/tmp/draw-image-e2e`, создаваемый/очищаемый в `beforeAll`. При параллельном запуске 10× `npx vitest run` процессы конкурировали за один output-каталог: процесс A удалял `TMP` (вместе с `e2e.png` + `e2e.meta.json`, только что написанными процессом B) → assertion `expected 'skipped' to be 'rendered'` падал. `process.pid` уникален на параллельный vitest-процесс → per-process TMP устраняет race. Тот же bug class что и #183, но `e2e.test.ts` не вошёл в список affected-файлов issue #183 (чинился в #186, где явно отмечено в Pending: "Issue #185: тот же bug class в `tests/e2e.test.ts` — отдельный PR").

Верификация: одиночный `npx vitest run .opencode/draw-image/tests/` — 58/58 зелёные; параллельный 10× `npx vitest run .opencode/draw-image/tests/e2e.test.ts` — 10/10 зелёные, без `skipped vs rendered`.

## Pending
-

## Watch out
- Спека issue #185 утверждала "afterAll уже есть — оставить cleanup", но фактически блок `afterAll` отсутствовал в теле `e2e.test.ts` (импорт был в строке 1, но не использовался). Добавлен `afterAll` cleanup по паттерну #186 — критерий приемки "no leftover" требует удаления output-каталога после тестов.
- Спека предлагала альтернативу `fs.mkdtempSync(path.join(os.tmpdir(), "draw-image-e2e-"))`, но использован `process.pid` suffixed path — соответствует паттерну #186 (консистентность с 7 уже зафиксированными файлами).
- `mkdtempSync` не использовался — `process.pid` suffixed path достаточен для внешней параллельности (отдельные процессы vitest); для intra-process threads у vitest по умолчанию forks pool, PID разный у каждого воркера.