# ADR-080: Per-process temp dir in renderToPng test helpers

## Статус
Accepted (2026-07-31)

## Контекст

Тестовые хелперы `renderToPng` в `tests/render.integration.test.ts` и `tests/render.optional.integration.test.ts` рендерили SVG через двухфазный процесс:
1. `writeFileSync(path.join(TMP, "input.svg"), svg)` — запись в единственный fixed-path файл в общем `TMP`-каталоге (`/tmp/draw-image-integration`, общий для всех параллельных vitest-процессов).
2. `spawnSync("node", ["render.mjs", tmpSvg, outPath])` — дочерний процесс читает файл и рендерит PNG через sharp.

При параллельном запуске нескольких vitest-процессов (внешняя параллель — `npx vitest run` × N concurrently) процессы разделяли один `input.svg`: один процесс обнулял/перезаписывал файл, пока другой его читал → `render.mjs` падал с `Input Buffer is empty`. Это тестовый аналог бага #160 (продакшн `cli.ts`), но в хелпере, а не в CLI. Воспроизведено: 10 параллельных прогонов → run 9 упал с `Input Buffer is empty`.

## Решение

Использовать уникальный temp-каталог на каждый вызов `renderToPng` через `mkdtempSync` под системным `os.tmpdir()` с PID в префиксе:
```ts
const tmpDir = mkdtempSync(path.join(os.tmpdir(), `draw-image-test-${process.pid}-`))
const tmpSvg = path.join(tmpDir, "input.svg")
try {
  writeFileSync(tmpSvg, svg)
  // ... spawnSync render.mjs ...
} finally {
  if (existsSync(tmpDir)) rmSync(tmpDir, { recursive: true, force: true })
}
```
и удалять каталог в `finally`-блоке после рендера (cleanup гарантирован даже при `throw`). `render.mjs` не изменён — он уже принимает path к SVG как argv, уникальность обеспечивает хелпер.

## Альтернативы

- **PID-суффикс на файл вместо каталога**: `path.join(os.tmpdir(), \`draw-image-test-input-\${process.pid}.svg\`)` — как в `cli.ts` (#160). Достаточен для race между процессами, но НЕ решает race между threads/воркерами одного vitest-процесса (один `process.pid`, несколько параллельных вызовов `renderToPng`). `mkdtempSync` даёт уникальность на каждый вызов, закрывая оба случая (граничный случай из спеки #177).
- **Уникальный каталог на процесс без `mkdtempSync`**: `path.join(os.tmpdir(), \`draw-image-test-\${process.pid}\`)` + `mkdirSync` — требует ручной гарантии уникальности и cleanup; `mkdtempSync` атомарно создаёт уникальный каталог за один вызов.
- **Передача SVG через stdin в `render.mjs`**: избегает temp-файла целиком, но требует переписывания `render.mjs` (чтение из stdin вместо `readFileSync(argv)`), что выходит за рамки спеки #177 и ломает контракт «`render.mjs` принимает path как argv».