WORKER-REPORT
Task
01M-WIRE-CENSUS — замер (без правки кода): исчерпывающий цензус формата
каталога пакетов vibevm «на проводе». Произвести ровно два файла —
WIRE-CENSUS.md (разделы 3.1–3.8) и этот отчёт. Git и cargo не запускать.
Changed files (each with why)
- 02
WIRE-CENSUS.md— создан; полный цензус каталог-провода (типы, поля, объединения, закрытые словари, версия, кругооборот, строгость, схемы). WORKER-REPORT-M-WIRE-CENSUS.md— создан; этот отчёт по шаблону.
03Никакие существующие файлы не изменялись.
Acceptance, point by point
- 04
WIRE-CENSUS.mdсуществует и несёт разделы 3.1–3.8 → DONE (файл создан, все 8 разделов с теми же заголовками и порядком). - Таблица типов покрывает все сериализуемые публичные типы периметра →
DONE (3.1: 18 каталог-файловых типов + 5 закрытых словарей + внешний
Group; отдельно перечислены HTTP-only конверты сервера). - Таблица полей покрывает все поля; у каждого заполнен столбец «различимы пусто и нет поля» → DONE (3.2: 86 строк, столбец заполнен у каждой; ДА / НЕТ / всегда).
- Каждое объединение найдено; для каждого — пересекаются ли ключи →
DONE (3.3: ровно одно объединение
RepomdFileEntry; наборы{kind,entries}и{size,sha256}не пересекаются, разбор однозначен; второго объединения нет). - Для каждого закрытого словаря — что делает читатель с неизвестным
значением, со ссылкой на код → DONE (3.4: для всех — ошибка разбора,
derived
Deserializefieldless enum без#[serde(other)]; такое поведение упомянуто уkinds.rs:76, тестыpackage_kind_rejects_unknown). - Про версию формата — ветвится ли по ней хоть что-нибудь → DONE (3.5:
не ветвится нигде в каталоге; только присваивается/читается/печатается;
контраст с
vibe.lock, где!=есть —lockfile.rs:430). - Вопрос кругооборота (3.6) отвечен точно, со ссылками → DONE (3.6: 6
call-сайтов
write_toповерх существующего каталога со ссылкамиadd.rs:51,122,remove.rs:35,57,reindex.rs:218,281,packages.rs:256,304,333; стартовая загрузкаserve.rs:77). - Пять чисел названы в отчёте → DONE (см. «Пять чисел» ниже).
- Ни одного изменения ни в одном существующем файле → DONE (созданы
только два новых файла;
git statusдо старта был clean, cargo/git не запускались).
Self-verify
- 05
grep -rn "deny_unknown_fields" crates/vibe-index/src/types crates/vibe-index/src/index/inverted.rs | wc -l→ 15. Это 15 каталог-структур со строгим чтением;CapabilityRow,PurlRow(inverted) иRepomdFileEntry(untagged) — без DUF. Совпадает с 3.1. grep -rn "#\[serde(untagged)\]" crates/vibe-index/src crates/vibe-registry/src/index_client→ ровно 1 совпадение:types/repomd.rs:42(RepomdFileEntry). Подтверждает «объединение без тега = 1», второго нет.grep -rn 'skip_serializing_if = ".*is_empty"' crates/vibe-index/src/types→ 21 строка; из них 14 — коллекции (Vec/BTreeMap), 7 — вложенные структуры (…Entry::is_empty). 14 коллекций подтверждает число из пакета в точности. (Подсчёт по типам поля: content.rs — 4, mod.rs — 4 коллекции + 7 вложенных, relations.rs — 6 коллекций.)- Чтение исходников без запуска cargo/git: все ссылки в
WIRE-CENSUS.mdвзяты прямымиRead/Grepпо дереву.
Пять чисел
- 06Wire-типов: 23 в периметре (18 каталог-файловых: 17 структур +
RepomdFileEntry) + 5 закрытых словарей-enum (PackageKind,NamingConvention,DeliveryMode,DirectoryTag,BindingSite) + внешнийGroupизvibe-coreна проводе (= 24 с ним). Пакет говорил «около 18» — это в точности каталог-файловые типы (17 структур + 1 union). - Полей всего: 86 (82 именованных поля структур + 4 поля в двух
вариантах
RepomdFileEntry). - Полей-коллекций, у которых пустое неотличимо от отсутствующего: 14 (подтверждено машинно; список имён в 3.2).
- Объединений без тега: 1 (
RepomdFileEntry; единственное объединение вообще). - Мест, где каталог перечитывается и переписывается: 6 call-сайтов
write_toповерх существующего каталога (add,remove,reindex/rescan-org, серверныеupsert,delete_version,delete_package), плюсinitпишет с нуля.
Decisions taken (each with why)
- 07Поправка к «≈18 типов» → 23 (+Group). Считал прямым обходом
types/**+index/inverted.rs+ реэкспортовtypes/mod.rs. 18 совпадает с каталог-файловыми типами (17 структур +RepomdFileEntry); дерево добавляет 5 закрытых словарей и внешнийGroup. Назвал своё число и способ, как требует раздел 4. - Подтверждение «14» без правки. Пересчитал grep-ом все
skip_serializing_if = "…::is_empty"с типомVec/BTreeMap— ровно 14. Дополнительно выделил 7 вложенных структур-полей с той же неразличимостью (они не коллекции, но семантически та же потеря). - «Версия — не версия». Прошёл grep
schema_versionпоcratesи проверил каждое чтение: сравнений (==/!=/match) дляRepomd/VersionEntryнет; единственное!=— вvibe.lock(lockfile.rs:430), это другая схема. Решил явно противопоставить, чтобы тезис «по ней никто не ветвится» был доказан, а не предположен. - Кругооборот — перечитывается и переписывается, но из типизированной
памяти. Прочитал
write_to,load_from,add/remove/reindex/ серверные обработчики. Решил не ограничиваться «да/нет», а дать таблицу «откуда данные» — потому что для решения о смене формата критично, что неизвестные поля не выживают (а из-за DUF — даже не читаются). - Клиент — терпим. Прочитал
index_client/wire.rs: view-структуры с#[serde(default)]без DUF; это образец поведения чужого читателя и ключевой контраст со строгими каталог-типами — вынес в отдельный вывод 3.7.
Deviations and resolved ambiguities
- 08В таблице 3.1 HTTP-only конверты сервера (
ListResponse,SearchResponseи т.д.) вынесены отдельным списком, а не в основную таблицу типов: 3.1 просит «какой файл каталога описывает тип», а эти типы в файлы каталога не пишутся (живой API). При этом они включены в цензус, чтобы провод был покрыт полностью. Groupпосчитан внешним (определён вvibe-core), но явно показан в таблице: он реально на проводе (полеgroup), и его валидация при чтении (try_from = "String") — часть контракта.
Not done / leftovers
- 09none