Перейти к основному содержимому

Служебное

Замер от: 2026-08-14 · чем проверено: ZAMER-KARTY-BLOKOV-2026-08-14.md, ZAMER-BAZY-2026-08-14.md, прогон compile_s3_next_schedule.py --check Для кого: кто разбирается, почему что-то не запустилось, не собралось или не доказало своего происхождения.

Что делает

Блок, который держит всё остальное: запускает по расписанию, сторожит, доказывает происхождение данных и пускает к себе не всех. В прежней карте этого блока не было целиком — между «что система делает» и деталями лежала догадка.

По дереву: планировщик — 28 модулей (marketplace-collector-v3/scheduler/*.py), мониторинг — 16 (marketplace-collector-v3/monitoring/*.py). В расписании на s3 26 записей (подтверждено двумя независимыми замерами); из них мониторинг: freshness_check каждый час, daily_reconciliation в 09:45, shadow_watch в 09:30 и ещё три прогона run_monitor.sh (kernel_freshness, canon_next_compare, parity_breakdown).

Точка входа в код

schedules/s3-next.yaml — единый реестр расписания. Из него компилятор marketplace-collector-v3/scripts/compile_s3_next_schedule.py порождает marketplace-collector-v3/scripts/crontab.s3-next.txt, и порождение обязано быть побайтово воспроизводимым (--check). Чтение блока начинается отсюда: реестр объясняет, что и когда зовётся.

Чем задаётся

Четыре рода служебного, по одному источнику на каждый:

  1. Планировщик и расписание. Реестр schedules/s3-next.yaml; правила имени задания, полей cron и окружения — в самом компиляторе; договоры шагов — marketplace-collector-v3/schedule_contract.py.
  2. Сторожа. Единый вход по симптому уже сделан: docs/guards/README.md. Здесь не перечисляем — таблица симптомов там.
  3. Расписки и происхождение. Договор в marketplace-collector-v3/intake/: каждый прогон сбора несёт в collection_run дайджест описания (spec_digest), точный коммит рантайма (runtime_commit, Git SHA из договора запуска), дайджест договора запроса (request_contract_digest); сырой ответ хранится в raw_payload, а проверка входов ядра повторно хеширует его перед сборкой; расписка собирается из дайджестов содержимого, областей сбора и договора (intake/receipt_contract.py). Без них нельзя ответить, каким кодом и из какого ответа произведена строка, — и это ловится сторожем полноты расписок (R9, receipt completeness failed).
  4. Права. Три уровня: роли и разрешения Shield (view_any_*, page_*, config/filament-shield.php); бизнес-доступ «возможности × площадки» (config/access-control.php, EnforceBusinessAccess, AccessManager); области токенов Data API (data_api/auth.py). У super_admin явно назначено меньшинство прав — и это не дефект, а устройство: Shield перехватывает его роль до проверки (intercept_gate: 'before'), а AccessManager::isSuperAdmin даёт обход бизнес-прав, поэтому назначать ему права поштучно не нужно.

Какие правила обязан соблюдать

  • Cron руками не правится. Источник — реестр, а не файл: побайтовая сверка при выкладке убьёт ручную правку вместе с её смыслом.
  • Шесть таблиц schedule_slot_* объявлены миграцией marketplace-collector-v3/kernel/schemas/migrations/2026-07-16_schedule_slot_ledger.sql, пусты на 14.08.2026, хотя писатель в дереве есть: класс LedgerStore (scheduler/ledger_store.py:56) с методами insert_slot_if_missing (:523) и append_event (:593), подкласс SlotLedger (scheduler/slot_ledger.py:41) и вызовы записи из scheduler/ledger_claims.py:55,88-176 и scheduler/ledger_completion.py:289. SlotLedger объединяет эти операции, а scheduler/control_plane.py:338 создаёт его для типизированной управляющей операции. В штатном cron точки активации нет: в crontab.s3-next.txt нет ни одной записи планировщика, а привязка к действующему сборщику — bind_started_collection_run_if_requested (scheduler/collector_binding_client.py:84-125) — без унаследованного дескриптора окружения возвращает None и ничего не пишет. Механизм построен и не включён, и это объявленное состояние, а не дефект: контракты P3-B (строка 3: DEPLOYED / DARK / NOT ACTIVATED; строки 9–10: нет scheduler principal, grant, timer, reconciler, cron mutation) и P3-C (строка 3 — тот же статус; строки 7–8: launcher, timer/reconciler, cron-запись по-прежнему отсутствуют) объявляют невключение намеренным. Кто и когда активирует — по-прежнему вопрос к владельцу.
  • Пустая collector_lease — это другое. Строки появляются на время работы сборщика (spec_runtime/lease.py) и снимаются после; пустота означает «сейчас никто не собирает», а не «механизм мёртв». Не чинить исправное.
  • Алерты не глушатся. Сторож, который молчит, — это потерянная строка в данных, а не сбережённые нервы.
  • Таблица defect_registry — реестр машинных дефектов, шаг 1 из пяти (решение владельца 15.08.2026: «чтобы ошибки складывались куда-то в реестр»). Миграция marketplace-collector-v3/kernel/schemas/migrations/2026-08-15_defect_registry.sql вписана в выкладку, писателя пока НЕТ намеренно: сторожей к ней подключает шаг 2, он идёт только после приёмки таблицы. Нормализатор отпечатка — monitoring/defect_registry.py. Полная постановка — ZADANIE-REESTR-DEFEKTOV.md.

Чем проверяется

python3 marketplace-collector-v3/scripts/compile_s3_next_schedule.py --check
python3 -m pytest marketplace-collector-v3/tests/test_s3_next_schedule_slots.py \
marketplace-collector-v3/tests/test_schedule_slot_ledger.py -q
python3 -m pytest marketplace-collector-v3/tests/test_collection_input_receipts.py -q
APP_BASE_PATH="$PWD" php vendor/phpunit/phpunit/phpunit tests/Feature/BusinessAccessTest.php

Первое — побайтовое совпадение порождаемого crontab с хранимым; остальные команды проверяют реестр слотов, расписки и бизнес-доступ. APP_BASE_PATH удерживает Laravel в текущем worktree, если vendor/ подключён ссылкой. Тесты, которым нужна база (например, test_schedule_slot_ledger_mysql.py), в обычном прогоне пропускаются — про это честно писать skipped, см. ниже.

Чего делать нельзя

  • Не править cron руками и не запускать legacy-сбор по кронам наобум — канон порождается из реестра, и расхождение ломает выкладку (сверка побайтная).
  • Не считать пустые schedule_slot_* поломкой, которую надо «оживить» вписыванием писателя куда попало: кто должен вести учёт слотов — вопрос к владельцу (контракты P3-B/P3-C: DEPLOYED / DARK / NOT ACTIVATED), а не повод для самодеятельности.
  • Не стирать и не ослаблять расписки ради скорости. Дайджест описания и коммит рантайма обязательны для договора запроса: без них прогон с распиской не начнётся вовсе.
  • Не раздавать права «на глаз». Роли преднастроены (docs/domain/ACCESS-CONTROL.md); назначение super_admin меньшинства прав — устройство, а не пример для подражания.

Что НЕ установлено

  • Кто и когда должен активировать учёт слотов schedule_slot_* — состояние установлено, момент — нет: контракты P3-B (строка 3; граница — строки 9–10) и P3-C (строки 3, 7–8) объявляют DEPLOYED / DARK / NOT ACTIVATED — активационных частей намеренно нет. Момент активации — по-прежнему решение владельца, а не дефект кода.
  • Заполненность колонок таблиц мониторинга (gwptd_monitoring, 16 таблиц, 9 пустых на 14.08) — поимённо не замерено; образец такой работы — DOKAZATELSTVA-PUSTYH-KOLONOK.md.
  • Число явно назначенных super_admin прав в боевой базе — исполнитель базы не имеет; утверждение про меньшинство взято из постановки, а не из запроса.

Куда за подробностью