crdt-op

Чеклист добавления или изменения операции CRDT доски (стикеры, перемещение, группы, голоса) в packages/crdt — семантика конфликтов, дельта, слияние, обязательные property-тесты, валидация на сервере,

SKILL.md

GitHub

crdt-op — новая операция над доской

Сходимость доски доказывается свойствами merge. Одна операция, нарушившая их, ломает доказательство для всего проекта, поэтому чеклист проходится целиком.

Чеклист

  1. Семантика. У каждого нового или изменённого поля есть строка в таблице §1.4 docs/spec/consistency-model.md (Kind/Field/Значения/Политика: «все варианты» или «победитель по метке»). Разные поля разрешаются независимо — отдельной попарной таблицы конфликтов операций в модели нет, см. § 2. Нет нужной строки — сначала /write-spec.
  2. Протокол. zod-схема дельты в packages/protocol; лимиты размера (длина текста, число supersedes) заданы в схеме.
  3. Дельта. packages/crdt/src/ops/<op>.ts: чистая функция (state, params, clock) → delta. Время, ID и случайность приходят параметрами.
  4. Слияние. Только через существующие примитивы полурешётки (MV-регистр, 2P-set, объединение по dot). Новый примитив → ADR и отдельный полный набор свойств для него.
  5. Материализация. Обход коллекций — после сортировки по ключу. Победитель — max(lamport, actorId). Никакой зависимости от порядка вставки в Map/Set.
  6. Генераторы. Операция добавлена в packages/crdt/test/arbitraries.ts — иначе property-тесты её не видят.
  7. Обязательные свойства (общие наборы параметризованы генераторами, проверить, что новая операция в них участвует):
    • lattice.prop — коммутативность, ассоциативность, идемпотентность merge;
    • convergence.prop — перестановки, дубли, задержки → одинаковый materialize;
    • no-loss.prop — dot каждой операции присутствует в состоянии;
    • materialize.prop — независимость от порядка вставки;
    • compact.prop — materialize(compact(s)) == materialize(s).
  8. Сервер. Валидация в обработчике: матрица прав (docs/security/permissions.md), фаза, лимиты. Если проверка не нужна — комментарий с причиной.
  9. Симулятор. Операция добавлена в генератор операций packages/sim.
  10. Прогон. npm run test:prop && npm run test:sim, затем npm run check.

Типичные ошибки

  • Date.now() / crypto.randomUUID() внутри packages/crdt.
  • Object.keys/for...of по Map без сортировки в materialize.
  • Удаление, которое физически убирает запись: одновременная правка «воскрешает» стикер или теряется. Удаление — только отдельное значение в регистре deleted.
  • Доверие actorId и lamport из сообщения клиента на сервере.
  • Упавший property-тест «починен» уменьшением генератора. Правильно: seed и минимальный контрпример → регрессионный тест → исправление.