# B-3R: довести до PR и зелёного Linux CI

## Состояние

Рабочая копия `C:\Users\Ochenstarik\projects\server-monitor-manager-task3-b3`, ветка `hermes/task3-b3-fact-reconciliation`, база `b11c277`. Изменения **не закоммичены**: 23 отслеживаемых файла, +1735/−145, плюс новый файл `src/ServerMonitorManager.Control/ControlJsonContext.cs`.

Ветки на GitHub нет, PR нет, CI не запускался ни разу.

## Что проверено как сделанное

Сверял по коду рабочей копии, а не по отчёту:

| Пункт | Состояние |
|---|---|
| R1, пакетная верификация | `FinalizeBatchAsync` и единственный `finalRules = await applier.ListRulesAsync(…)` — реализовано |
| R2, класс `Deferred` | присутствует, инвариант классификации с диагностикой в `LinkService.cs:836` |
| R4, source-generated audit | `LinkOrphanAuditDetails` + `ControlJsonContext.Default.LinkOrphanAuditDetails`, новый `ControlJsonContext.cs` |
| R5, integration test | `link-list` в fake helper, 10 вхождений |
| R6, fail-open default | `ListRulesAsync` — обычный член интерфейса, тела по умолчанию нет |
| Мусор в статусе `nodes.tsv` | `node_status_pattern`: невалидный формат → 78, валидный не-`active` → 80 |

Содержательная часть закрыта. Осталась доставка.

## Что доделать

**1. Проверить бюджет привилегированных вызовов.** В `ConvergeAsync` остались вызовы `VerifyExactFactualCountAsync` на строках 487, 496, 505, 514 — помимо пакетной верификации через `FinalizeBatchAsync`. Убедиться, что проход без расхождений выполняет ровно один `link-list`, а проход с `k` мутациями — ровно два. Если пер-мутационные вызовы остались в пути полного прохода, бюджет нарушен и требование R1 не выполнено. Если они относятся к другим путям (`CreateAsync`, `DisableAsync`, TTL) — это допустимо, но должно быть явно сказано в отчёте.

**2. Прогнать Control suite на Linux.** Это отдельное требование, а не формальность: integration-тест помечен `OperatingSystem.IsLinux()` и на Windows молча пропускается. Именно так дефект H2 и дожил до ревью в прошлый раз.

**3. Прогнать orphan-путь на опубликованном `linux-x64 PublishTrimmed` артефакте** и приложить содержимое audit-записи. Reflection-сериализация заменена на source-generated, но проверка на trimmed-сборке — единственное доказательство, что путь исполняется.

**4. Семь обязательных тестов** из задания `smm-hermes-task-b3r-2026-08-06.md`, раздел «Тесты, без которых задание не принимается». Проверить наличие каждого поимённо.

**5. Коммит, push, PR.** Ветка `hermes/task3-b3-fact-reconciliation`. Дождаться завершения CI **до** того, как писать в описании PR о проверках.

## Критерий приёмки

- PR создан, CI зелёный — впервые для этой ветки;
- Control suite прогнан на Linux, результат приложен;
- бюджет вызовов `link-list` подтверждён числом, а не утверждением;
- семь обязательных тестов присутствуют и проходят;
- отчёт раздельно перечисляет: что локально, что в CI со ссылками, что не запускалось;
- независимый review получил полный текст `smm-hermes-task-b3r-2026-08-06.md` и `B3R_SPEC.md`.

## Отдельно

Физическая приёмка на трёх серверах готовится параллельно — runbook `smm-acceptance-runbook-2026-08-07.md`. Она не входит в это задание, но именно merge B-3R делает её осмысленной: до него реконсиляция от фактического состояния не в `main`.

Статус после merge — `merged / verified, physical acceptance pending`.
