# 08 — Требования к данным (ORCH-065)

## Изменение схемы: `jobs.pid`

| Поле | Значение |
|------|----------|
| Таблица | `jobs` |
| Колонка | `pid` |
| Тип | `INTEGER` (nullable, без DEFAULT) |
| Назначение | pid агентского процесса (`subprocess.Popen.pid` из `launcher._spawn`) для liveness-детекции зомби job-reaper'ом (Tier-1) |
| Механизм миграции | `_ensure_column(conn, "jobs", "pid", "INTEGER")` в `db.init_db` — идемпотентно, no-op если колонка уже есть |
| Безопасность на live prod DB | ДА. Тот же паттерn уже применён к `jobs.transient_attempts`, `jobs.available_at`, `events.delivery_id`, `agent_runs.*`. `ALTER TABLE ADD COLUMN` в SQLite — мгновенная метаданная-операция, не блокирует и не переписывает строки |
| Заполнение | в `_spawn` рядом с существующим `UPDATE jobs SET run_id=?, started_at=datetime('now') WHERE id=?` добавить `pid=?` (`proc.pid`). Старые строки остаются `pid IS NULL` → для них Tier-1 неприменим, работают Tier-2/Tier-3 |

## Что НЕ меняется
- `STAGE_TRANSITIONS`, реестр `QG_CHECKS` — без изменений (это контракты).
- Схема `agent_runs` — без изменений (`finished_at`/`exit_code` уже есть — основа Tier-2).
- Файл-схема merge-lease `.merge-lease-<repo>.json` — без изменений (`pid`,
  `acquired_at`, `branch`, `work_item_id`, `task_id` уже пишутся
  `acquire_merge_lease`).
- `jobs.status` enum (`queued|running|done|failed`) — без изменений; новый статус
  `reaping` НЕ вводится (атомарного guard `WHERE status='running'` достаточно).

## Совместимость / откат
- Откат миграции не требуется: лишняя nullable-колонка безвредна при
  `reaper_enabled=false`.
- `pid IS NULL` (строки до миграции, или если запись pid не успела) → reaper не
  делает Tier-1, опирается на Tier-2 (exit_code) и Tier-3 (потолок). Поведение
  деградирует gracefully, ложноположительных реапов не возникает.
