Служебное
Замер от: 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). Чтение блока начинается отсюда: реестр объясняет, что и когда зовётся.
Чем задаётся
Четыре рода служебного, по одному источнику на каждый:
- Планировщик и расписание. Реестр
schedules/s3-next.yaml; правила имени задания, полей cron и окружения — в самом компиляторе; договоры шагов —marketplace-collector-v3/schedule_contract.py. - Сторожа. Единый вход по симптому уже сделан: docs/guards/README.md. Здесь не перечисляем — таблица симптомов там.
- Расписки и происхождение. Договор в
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). - Права. Три уровня: роли и разрешения 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прав в боевой базе — исполнитель базы не имеет; утверждение про меньшинство взято из постановки, а не из запроса.
Куда за подробностью
- docs/guards/README.md — все сторожа по симптому.
- schedules/s3-next.yaml — сам реестр расписания.
marketplace-collector-v3/intake/envelope.py,intake/receipt_contract.py— расписки.- docs/guards/receipt-completeness.md — сторож R9.
- docs/domain/ACCESS-CONTROL.md — модель доступа
/new. - docs/backend/generated/ENDPOINTS-CATALOG.md — окна и лимиты, с которыми согласовано расписание.