v1.0.178: схема Опуса — генератор + симулятор + моя оценка
This commit is contained in:
@@ -0,0 +1,122 @@
|
|||||||
|
# Схема Опуса — генератор + симулятор (v1.0)
|
||||||
|
|
||||||
|
Ответ Опуса от 25.06.2026 на запрос `History/opus-generator-request.md`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Оценка схемы
|
||||||
|
|
||||||
|
### Сильные стороны
|
||||||
|
|
||||||
|
1. **v1→v2 diff-пары** — ключевая идея. Генератор закладывает конкретные изменения между версиями спецификаций (цена, объём, ADD/DELETE/UPDATE), и верификатор проверяет что compare нашёл именно их. Это даёт детерминированную проверку самой важной функции сервиса.
|
||||||
|
|
||||||
|
2. **manifest.json как ground truth** — каждая проверка сверяется с эталоном, а не с «примерно ожидаемым». Никакой неоднозначности.
|
||||||
|
|
||||||
|
3. **Пул услуг из реальных данных** — стойко-место, PDU, L2-канал, cross-connect, Cloud, IPv4. Не выдуманные, а те что в реальных файлах.
|
||||||
|
|
||||||
|
4. **17 ошибочных кейсов** — покрытие крайне широкое: от битого XML до сиротских спецификаций.
|
||||||
|
|
||||||
|
5. **Структура папок** — `testgen/` + `sim/` с чётким разделением генерации и симуляции.
|
||||||
|
|
||||||
|
### Что нужно уточнить/доработать
|
||||||
|
|
||||||
|
1. **Симулятор: API или браузер?** Опус описывает «реальное приложение (API/UI)». Два варианта:
|
||||||
|
- **curl-симулятор** (только API): дёргаем `/upload`, `/api/classify-batch`, `/api/groups`, `/process-v2`. Быстро, дёшево, но не проверяет фронтенд (duplicate confirm, renderFiles, SSE в UI).
|
||||||
|
- **Playwright** (полный UI): открывает браузер, кликает кнопки, читает DOM. Медленно, но проверяет ВСЁ включая confirm-диалоги.
|
||||||
|
- **Рекомендация**: curl для генерации/классификации/групп + выборочно Playwright для UI-специфичных сценариев (дубликаты, confirm, удаление).
|
||||||
|
|
||||||
|
2. **.doc файлы** — парсинг `допник-1-XXX002-01200_3.doc` не удался (старый формат). Нужен LibreOffice для конвертации, либо исключить .doc из генерации и использовать только .docx.
|
||||||
|
|
||||||
|
3. **Стресс-сценарий F** — rapid-fire загрузки во время classify. Это может быть сложно воспроизвести и проверить. Вероятно, отложить на потом.
|
||||||
|
|
||||||
|
4. **Количество файлов** — раскладка даёт ~92 файла + edge cases. Можно докрутить до ровно 100 добавив ещё дубликатов или мусора.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Исходная схема Опуса
|
||||||
|
|
||||||
|
### Часть 1 — Генерация ~100 файлов
|
||||||
|
|
||||||
|
**Базовая структура:** 10 компаний × 10 договоров × (спецификация v1 + v2 + 1-3 допника)
|
||||||
|
|
||||||
|
**Раскладка:**
|
||||||
|
| Категория | Кол-во | Зачем |
|
||||||
|
|---|---|---|
|
||||||
|
| Договоры (валидные) | 10 | по 1 на компанию |
|
||||||
|
| Спецификации v1 | 10 | базовая версия |
|
||||||
|
| Спецификации v2 (ревизия) | 10 | diff для сравнения |
|
||||||
|
| Допники | 18 | 1–3 на договор |
|
||||||
|
| Битые/edge .docx | 15 | ошибки парсинга/классификации |
|
||||||
|
| Форматы .doc/.pdf | 12 | ветка конвертера |
|
||||||
|
| ZIP-архивы | 5 | внутри — наборы файлов |
|
||||||
|
| Дубликаты (имя/контент) | 10 | upload-логика |
|
||||||
|
| Мусор (не договор) | 10 | негативная классификация |
|
||||||
|
| **Итого** | **~100** | |
|
||||||
|
|
||||||
|
**Оси вариативности:**
|
||||||
|
- Компания: ЗАО/ООО/АО/ПАО/ИП, латиница/кириллица
|
||||||
|
- Номер: 5 цифр, опц. суффикс `_N`, edge — буквы/длинный/пустой
|
||||||
|
- Дата: 12.2025–06.2026, форматы `01.02.2026` и «01 февраля 2026»
|
||||||
|
- Цены: базовые ±20%, разрядность с пробелом
|
||||||
|
- Услуги (пул): стойко-место, PDU, L2-канал, IPv4 /30 и /32, cross-connect ВОЛС/UTP, Cloud Intel/AMD, Интернет, порт, подсеть
|
||||||
|
- Таблица: 3–12 строк, 6 или 7 колонок
|
||||||
|
|
||||||
|
**Различия v1→v2 (для компаратора):** изменение цены, изменение объёма, добавленная услуга, удалённая услуга, переименование, сдвиг даты, пересчёт итога.
|
||||||
|
|
||||||
|
**Ошибочные кейсы (17 шт):** нет номера, нестандартный заголовок, битый XML, пустой файл, только таблицы, только текст, .doc формат, битый PDF, дубликат имени, дубликат контента, гигант (500 строк), не-договор, сирота (спека без договора), рассинхрон (имя файла ≠ номер в тексте).
|
||||||
|
|
||||||
|
**Parent-child:** ключ — НОМЕР. Генератор связывает договор→спеку/допник по НОМЕРу.
|
||||||
|
|
||||||
|
**Шаблоны python-docx:**
|
||||||
|
- Билдеры: `build_contract(ctx)`, `build_spec(ctx)`, `build_addendum(ctx)`
|
||||||
|
- ctx = {company, number, date, parties, services[], totals}
|
||||||
|
- Хелперы: `add_title`, `add_section`, `add_services_table`
|
||||||
|
- Битый XML: валидный docx → распаковать zip → испортить document.xml → запаковать
|
||||||
|
- .doc: docx → libreoffice --convert-to doc
|
||||||
|
- Битый PDF: docx → pdf → обрезать байты
|
||||||
|
|
||||||
|
### Часть 2 — Симулятор
|
||||||
|
|
||||||
|
**Словарь действий:** upload, delete, classify, groups, compare (SSE), confirm/cancel, reset.
|
||||||
|
|
||||||
|
**Сценарии:**
|
||||||
|
- **A. Хэппи-путь:** договор + спека v1 + v2 → classify → группа → compare → diff совпал
|
||||||
|
- **B. Зигзаг:** загрузил 3 → удалил 1 → добавил 2 → classify → проверить консистентность
|
||||||
|
- **C. Bulk:** все ~100 разом → classify → число групп, битые ✗
|
||||||
|
- **D. Тупые действия:** дубликат (OK/Отмена), удалить всё, смешать форматы, classify на нуле, compare с одной версией
|
||||||
|
- **E. ZIP:** валидный, с дубликатами, с битым файлом внутри
|
||||||
|
- **F. Стресс:** случайные паузы, rapid-fire, загрузка во время classify
|
||||||
|
|
||||||
|
**Тайминги:** think-time (random 0.1-3с), classify — поллинг, compare — SSE до done/таймаут.
|
||||||
|
|
||||||
|
### Часть 3 — Верификация
|
||||||
|
|
||||||
|
После каждого шага:
|
||||||
|
- `state.files` count == ожидаемого
|
||||||
|
- Статусы ✓/✗ соответствуют (битые → ✗)
|
||||||
|
- После classify: группы есть, состав по НОМЕРу верный
|
||||||
|
- Сироты без краша
|
||||||
|
- Compare: diff == заложенному (ground truth из manifest.json)
|
||||||
|
- Дубликаты: счётчик после OK ≠ после Отмена
|
||||||
|
- Нет 500-х, нет необработанных исключений
|
||||||
|
- Идемпотентность classify
|
||||||
|
|
||||||
|
**Ground truth:** `manifest.json` — что сгенерировано + ожидаемые группы и diff-ы.
|
||||||
|
|
||||||
|
### Структура папок
|
||||||
|
|
||||||
|
```
|
||||||
|
testgen/
|
||||||
|
pools.py # услуги, компании, цены
|
||||||
|
templates.py # build_contract / build_spec / build_addendum
|
||||||
|
corrupt.py # порча docx/pdf, конвертация .doc
|
||||||
|
generate.py # оркестратор → out/ + manifest.json
|
||||||
|
out/{valid,errors,formats,zips,duplicates}/
|
||||||
|
manifest.json # ground truth
|
||||||
|
|
||||||
|
sim/
|
||||||
|
actions.py # обёртки над API
|
||||||
|
scenarios.py # A..F
|
||||||
|
verify.py # чек-лист
|
||||||
|
run.py
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user