# Итоговая ведомость заказчику: docx-сверка на 4 колонки

## When to Use

Когда просят «проверку тома ИОС1.1 / ЭОМ», «сверку проверок» или просит внести
замечания в существующую docx-таблицу сверки (шаблон вида «ВОПРОС | МАСТЕРМАЙНД | …»).
Это финальный формат результата — не заменяется markdown-отчётом.

Формат, который принимается как результат проверки тома — не markdown-отчёт,
а **docx-таблица сверки**: «ВОПРОС | МАСТЕРМАЙНД | AI_Lab_SCRUM Co | РАСХОЖДЕНИЯ».

## Правила оформления

- 4 колонки; первые три — вопрос и два независимых заключения, четвёртая — расхождения.
- **Несоответствия — красным** (`RGBColor(0xC0, 0, 0)` в python-docx; в исходных файлах
  встречается `FF0000`).
- В колонке «Расхождения» — **готовая отредактированная формулировка**.
  Схему «было → отредактировано» не применять — колонку «было» не оставлять.
- Новые находки (шаги 1–3) добавляются **дополнительными строками целиком красным**,
  в первой колонке — суть со пометкой источника: «(шаг 1, код)» или «(шаг 3, аудитор)».
  Так видно, какой этап методики что дал — это и есть оценка метода.
- В конце — одно примечание: что проверено, чем, и что графическая часть не проверялась.

## Техника сборки (python-docx)

Скрипт: `scripts/build_review_docx.py`.

1. Читать **существующий** docx-шаблон и дописывать его, а не создавать с нуля:
   у шаблона уже есть стили, заливка шапки и прежние пометки.
2. Новую колонку добавлять копированием последней ячейки (`copy.deepcopy(cell._tc)`
   + `cell._tc.addnext(...)`) — в шапке и в каждой строке.
3. Новые строки — копированием строки-образца (`copy.deepcopy(t.rows[1]._tr)` +
   `t._tbl.append(...)`), затем заполнять ячейки 0..3.
4. **Обязательно дописать `w:gridCol`** в `w:tblGrid` под новую колонку. Без этого
   `table.columns` показывает 4, ячейки читаются, но Word рисует таблицу с ломаными
   ширинами — внешний дефект, который видно сразу. После — задать `cell.width`.
5. **Удалять устаревшее примечание** из шаблона: при дописывании остаются два
   противоречащих друг другу. Проверять `len(d.paragraphs)` до и после.
6. Тексты ячеек задавать через `cell.text = ""` + `p.add_run(text)` с `font.size = Pt(9)`;
   просто `cell.text = ...` теряет формат и даёт огромный шрифт.

## Логотип и колонтитулы AI_Lab_SCRUM_Co

Требование: на итоговой ведомости — **логотип и колонтитул AI_Lab_SCRUM_Co
сверху и снизу**. Логотип — `logo AI Lab SCRUM ENGINEERING`, присылается
пользователем как PNG **с прозрачным фоном и БЕЛЫМ текстом** (проверка:
`РГБА` + `getchannel("A")`, у белой части нейтральные каналы).

### Перекраска логотипа под светлый фон

На белой бумаге белый текст исчезает — нейтральные (белые/серые) пиксели нужно
перекрасить в тёмный, **не трогая оранжевый градиент**:

```python
if a == 0: continue
if abs(r-g) < 28 and abs(g-b) < 28 and abs(r-b) < 28:   # нейтральный (белый текст)
    po[x,y] = (0x1F, 0x24, 0x2B, a)                     # тёмный, альфу сохранить
else:
    po[x,y] = (r, g, b, a)                              # оранжевый — как есть
```

Затем `crop(alpha.getbbox())` и ресайз до ~900 px по ширине. Результат
проверять на белом фоне (`Image.alpha_composite` с белым) — белых ореолов быть
не должно, оранжевый градиент сохраняется.

### Вставка колонтитулов (python-docx)

- Логотип — **в верхний колонтитул**, а не в тело: `sec.header`, `is_linked_to_previous = False`,
  `run.add_picture(path, width=Cm(3.6))`. В теле при этом картинок оставаться не должно.
- **ЛОВУШКА: фиксированный таб-стоп.** Том бывает форматом A3 landscape
  (`page_width` 42 см), поэтому таб на 17 см не работает — текст встаёт по центру.
  Стоп считать от фактической области: `Emu(sec.page_width - sec.left_margin - sec.right_margin)`.
  Проверять по PDF не по блокам, а **по спанам** (`get_text("dict")` → `lines[].spans[]`),
  блоки дают всю ширину и создают ложное впечатление смещения.
- `paragraph_format.tab_stops.clear_all()` перед добавлением своего стопа — в шаблоне.
- Разделительная линия — `w:pBdr` (`bottom` у хедера, `top` у футера), цветом `E06000`.
- Ширины колонок таблицы тоже зависят от формата: для A3 брать ~9,5 / 10 / 11,5 / 11,5 см.
- Проверка результата — рендер в PDF через Word COM (`doc.SaveAs(path, FileFormat=17)`) и
  просмотр страниц; полезно проверить и первую, и последнюю страницу.

## Проверка после сборки

Пройтись по всем строкам и собрать множество колонок, где есть красные run'ы:

```python
red_cols = set()
for ci, cell in enumerate(row.cells):
    for para in cell.paragraphs:
        for r in para.runs:
            if r.font.color and r.font.color.rgb and str(r.font.color.rgb) == "C00000" and r.text.strip():
                red_cols.add(ci)
```

Ожидание: в старых строках красные — колонки 2 и/или 3; в новых — 0, 2, 3.
Если в старой строке нет ни одного красного — там просто нет расхождений («—»).
