--- title: "sched F&F r8 — стенд верификации (schedule-as-entity)" type: concept tags: [sched, fnf, verification, stand, verdaccio, schedule-as-entity, docker] sources: [] related: [concepts/windows-docker-test-harness-gotchas.md] updated: 2026-08-18 --- # sched F&F r8 — стенд верификации Кросс-агентный цикл F&F (findings & fixes): sched-команда публикует пакеты в verdaccio, admin-сессия верифицирует на стенде и репортит находки через инбокс (`sched/.agents/inbox/`). Раунд r8 = «schedule-as-entity» (движок тикает по schedule-строкам). Цикл идёт письмами: intro → отчёт → фикс → перепроверка → следующий пункт. ## Стенд - Путь: `C:\Users\vitya\projects\.admin\.tmp\sched-r8\` (gitignored, живёт на диске). - package.json: **@sched/core 0.40.1 / daemon 0.2.0 / storage-{mysql,postgres,mongo} 0.3.1** из verdaccio (`npm install --registry=https://verdaccio.kzntsv.site/`). `legacy/` — старый core 0.35.1 для генерации v0.6-БД. - Docker-контейнеры (как в CI sched): `sched-mysql-test` :3308, `sched-mariadb-test` :3307, `sched-postgres-test` :5433, `sched-mongo-test` :27017; root:test / postgres:test. ## Репро-скрипты (15 шт., `.tmp/sched-r8/*.mjs`) **Миграции / адаптеры (№1):** - `migration-test.mjs` — sqlite v0.6→v0.7 (эталон синтеза) - `adapter-migration-test.mjs` — F2: mysql/pg v3→v5, синтез легаси-строки, due стреляет - `mongo-synthesis-test.mjs` — F2 mongo: first-open синтез, no-dup, non-empty gate. Легаси-док: коллекция `sched_tasks`, `config.data` (не `data`), `paused`/`disabled` обязательны (иначе null → не в due) - `priority-order-test.mjs` — F1: task priority 10 наследуется на строку - `adapters-spotcheck.mjs` — 12/12 CRUD+dedupKey-upsert на 4 адаптерах - `tasks-json-test.mjs` — модель tasks.json (schedules:[...], fail-fast legacy key) - `contract-parity.test.mjs` — vitest contract-сьют 5 адаптеров (см. гочу №2) **Движок (№2, 75 проверок):** - `engine-runs-test.mjs` (16) — scheduleId/data/trigger на schedule-ранах; manual (null+дефолты); retryRun (снапшот+retryOf) - `engine-due-claim-test.mjs` (10) — priority-порядок, ceiling с блокирующим раннером, pause, once, catch-up - `engine-retry-test.mjs` (27) — ретраи на строках (retryCount/backoff×multiplier/failCount/onRunFinal), override, retryOf-цепочка - `engine-watchdog-test.mjs` (14) — reap обоих наборов локов, heartbeat real-clock, recoverOrphanRuns - `engine-async-test.mjs` (8) — async poll через schedule-раны, poll timeout **Политики (№3, 21 проверка):** - `engine-policy-test.mjs` — whole-no-merge (override не наследует поля дефолта), snapshot-семантика пендинг-ретрая, pause AND два уровня, manual=дефолты задачи, priority-микс ## Что подтверждено (контракт) - **Ceiling сериализует через тики**: две due-строки одной задачи стреляют в РАЗНЫХ тиках (sibling-claim отклоняется атомарно). Параллелизм только между задачами. - **onRunFinal** — на любом терминальном ране (успех тоже), не только на persistent-failure; «алерты только на фейлы» — фильтр consumer'а. - **retryCount на строке** = consumed-попытки (кумулятив: после 2 фейлов = 2). - **resolveSchedulePolicy** = `schedule.retry ?? task.retry` целиком; explicit `priority: 0` уважается как есть. - **Snapshot-семантика**: правка политики не пересчитывает дедлайн пендинг-ретрая; свежая политика — со следующего диспатча. - **pause AND**: `task.paused` гейтит все расписания (движок), `schedule.paused` — одно (due-запрос). - **manual triggerTask** = дефолты задачи (data, без schedule-политики), расписание не двигается. ## Как продолжить (№4 API / №5 UI) 1. Бамп версий в package.json стенда → `npm install --registry=...`. 2. Новые проверки — отдельный `.mjs` по паттерну существующих (`check()` + SUMMARY), изолированные DB на сценарий. 3. Отчёт — письмо в `sched/.agents/inbox/` с фронтматтером `from: admin`, формат «делал → ожидал → получил → раздел доки». Не чинить, не пушить, их доску не трогать.