5.6 KiB
5.6 KiB
Context
do_wiki_sync обходит дерево от корня (build_children + walk), читает текст каждой страницы
(CmfDocument.get … ["code", "name", "text"]) и шлёт пачки страниц POST /agent/wiki/pages (≤50 страниц, ≤4 МБ JSON),
затем отчитывается done {root_title, codes, eva_calls}. Хаб с change wiki-history дописывает в параметры выдачи
known_versions и принимает версии отдельным маршрутом.
Проверено на живой Eva 28.10.2026:
CmfDocumentHistory.listсfilter=[["parent_id", "==", "CmfDocument:<uuid>"]]работает;parent.code— ошибка-32001(вложенный фильтр).- Поля версии:
code(DOCH-…),cmf_created_at(ISO со смещением+03:00),cmf_author_id,text(полный HTML, до ~56 тыс. символов),has_published,cur_workflow.cmf_authorпо имени поля раскрывается в объект сnameиlogin(как уCmfDocument). - Черновик (
has_published = false) Eva меняет на месте.
Goals / Non-Goals
Goals: опубликованные версии страниц дерева — хабу, без повторной перекачки известных; работа с хабом без истории.
Non-Goals: см. proposal.md.
Decisions
- Шаг версий — после страниц, в той же команде. Страницы отправлены — затем версии; отчёт один. Порядок страниц — порядок обхода.
- Выборка по странице дерева. Для каждой страницы обхода —
CmfDocumentHistory.listс фильтромparent_id= id страницы из обхода (doc["id"]), полями["code", "cmf_created_at", "has_published", "cmf_author"], страницами поPAGE_SIZEс той же защитой от несоблюденияslice, что уlist_docs(общий помощник для класса). Опубликованные отбираются у себя (has_published is True): фильтр Eva по этому полю не проверялся. - Текст — только новых. Версия, чей код есть в
known_versions[<код страницы>], пропускается без запроса текста. Для остальных —CmfDocumentHistory.getпо коду с полями["code", "text"];html=text(не строка — пустая строка);attachments,links—classify_links(html, base), как у страниц. - Автор.
{login, name}изcmf_author; объекта нет или поля закрыты (_acl_fields) —{login: null, name: null}. - Пачки. Те же пределы, что у страниц: ≤50 версий и ≤4 МБ JSON на пачку; 413 от хаба — ошибка с кодом версии или
границами пачки (как
_send_pages). - Совместимость с прежним хабом. Ключа
known_versionsв параметрах нет — шаг версий не выполняется, в отчёте нетversions. Пустой объект{}— первый прогон, вся история. - Ошибки. Ошибка Eva на шаге версий (
EvaError, сеть после повторов) — командаfailedс текстом, как на шаге страниц; хаб оставит копию и историю прежними (решение 10 change хаба). Версия безcodeили безcmf_created_atпропускается с записью в лог. - Счётчики.
result.versions— число отправленных версий;eva_callsвключает вызовы шага версий. - Тесты.
tests/fake_eva.pyполучаетCmfDocumentHistory.list(фильтрparent_id) и.get(поcode); сквозной прогон с тестовым хабом — первая загрузка и догрузка одной новой версии.
Risks / Trade-offs
- Один вызов Eva на страницу при каждой синхронизации; при пачке новых версий — ещё по вызову на версию. Первый прогон
AWPCA (28 страниц, десятки версий) — порядка сотни вызовов с паузой
wiki_pacing. - Если Eva однажды поменяет текст опубликованной версии, агент её не перечитает (код уже известен хабу).
Decisions made without discussion
- 28.10.2026 — отбор опубликованных у себя, не фильтром Eva (решение 2). Обоснование: фильтр по
has_publishedне проверялся, а лишние метаданные дёшевы. Цена ошибки: чуть больше данных в ответе на страницу. - 28.10.2026 — пустой автор
{null, null}вместо отказа (решение 4). Цена ошибки: в ленте правка без имени. - 28.10.2026 — без
known_versionsшаг пропускается (решение 6). Цена ошибки: нет — прежний хаб маршрута версий не знает.