24 KiB
Промт бэкенд-сессии: ПАК-17 «канал B (18+) вживую» (ДВУХФАЗНЫЙ: дизайн → ратификация → стройка)
Статус: ФАЗА 1 ИСПОЛНЕНА И РАТИФИЦИРОВАНА (D39.26, 25.07) → ФАЗА 2 РАЗМЕЧЕНА И ОТКРЫТА. Дизайн-отчёт docs/archive/reports/PACK17_DESIGN_2026-07-25.md принят В РЕДАКЦИИ §14 (тело §0–13 читать ТОЛЬКО через §14; при расхождении побеждает §14) + ревью-шапка оркестратора. Фаза 2 стартует по §«ФАЗА 2» ниже — там ратифицированный «ровно так»-список; §«ФАЗА 1» оставлена как история задания.
Статус фазы 1: ВЫДАН 25.07.2026, оркестратор №7. Цель: 18+ контент (уровни 1–2) идёт через волновой стек по adult-каналу — permissive-провайдеры, refusal-обработка, механические гарантии маршрутизации. Ратифицированная база: D14 (состав канала B) · D19 (Mistral = переводчик канала B; register-оговорка эха D19.1; судьи 18+ п.6: Gemini fail-closed на эротике, Grok первичный) · D22 (развязки 18+/эха; L3-спека D22.7) · D4 (adult-цепочка = permissive-провайдеры; уже в конфигах: escalation.chains.adult: [grok-4.3]). Эмпирика полигона: experiments/10-explicit-benchmark (violence) · 11-erotica-benchmark.
Инварианты — «РОВНО ТАК» (ратифицировано; конфликт с кодом/доками → пинг оркестратору через владельца, НЕ интерпретация)
- В ДВИЖКЕ НЕТ ПОНЯТИЯ «18+» (директива владельца 25.07 — архитектурная). Движок несёт только GENERIC-механизм: content-label книги/глав (данные книги) × capability провайдера (данные models.yaml) × выбор цепочки (конфиг). «adult» — ЗНАЧЕНИЕ данных; ни один Go-идентификатор/ветка не именуется adult/18+/каналом B. Тот же механизм обязан нести будущие лейблы без правки Go — мысленный тест: archaic-register (D19.1-эхо grok на архаичном zh — та же фигура «свойство контента × способность модели»). Проактивный роутинг по лейблу — не оптимизация, а ToS-гигиена: провайдер без способности не должен ПОЛУЧИТЬ такой контент, независимо от того, откажет ли.
- Refusal-обработка — GENERIC и причино-агностичная: D12-таксономия детектит ФАКТ отказа (hard/soft), не причину; отказ по эротике/политике/чему угодно идёт ОДНИМ путём (регенерация → эскалация по цепочке лейбла → flag+skip, D2 — мусор не течёт в TM/экспорт). Причина отказа — только операторская диагностика. Параметризуется ПОЛИТИКА ЦЕПОЧКИ (конфиг), не код. Существующая таксономия не переписывается.
- 18+ уровень 3 — жёсткая линия: НЕ обрабатывать, НЕ анализировать, классификатор L3 в этом паке НЕ строить (спека D22.7 ждёт решений владельца по валидации).
eval/data/refusal_corpus/*НЕ открывать. L3 — политика ВХОДА (человеческий уровень), не механизм движка. - Live-вызовы с 18+ контентом — ТОЛЬКО по явной санкции владельца с его корпусом. Пак строится и тестируется на mock-провайдере + СИНТЕТИЧЕСКИХ безобидных фикстурах (маркер-прокси, не реальная эротика); книга и производные вне git.
- Capability-исключения — ДАННЫМИ: DeepSeek без adult-capability (ToS, стратревью 09.07), Anthropic без 18+ — строки в models.yaml, не Go-литералы имён; гарантия «label ⊄ capabilities → провайдер не получает контент» — компилируемая/тестируемая, fail-loud.
- Байт-точность no-adult пути: канал A (обычные книги) байт-идентичен — golden без пере-капчера; парити EXACT; adult-механика активируется только явной маркировкой.
- Ключи: xAI единый data-sharing, off перед продом (D27) — операционная петля владельца, в пак не тащить.
Отправные точки в код (сверь САМ — код первичен, это entry-points)
escalation.chains.adult в шиппинг-конфигах и его валидация · channel-aware фильтр цепочек заявлен зоной раннера в комменте pipeline-c1.yaml (НЕ построен) · refusal-классы internal/pipeline/disposition.go + internal/lang/data/refusal.txt · провайдер-модель internal/config/models.yaml+models.go (есть ли слот под permissive-флаг — инвентаризуй) · волновой драйвер waverun/stagerun (где стадия выбирает модель/цепочку).
ФАЗА 1 — ДИЗАЙН (кода не трогать; отчёт → СТОП → ратификация). Каждый пункт «реши сам и аргументируй»; советы = приоры, опровергаются аргументом/замером
- B1. Схема content-labels и гранулярность. Формат лейблов (данные книги: book.yaml/brief) и capabilities (models.yaml); книга / глава / чанк; кто маркирует в v1. Приор: v1 = ручная маркировка владельцем на уровне книги или глав; значение v1 — одно («adult»), но СХЕМА generic (множество лейблов); ПОЛИТИКА лейбла — тоже generic:
route-to-chain(adult → permissive-цепочка) ИЛИterminal(не обрабатывать вовсе; будущее значение «prohibited» = данные, движок значения не знает); авто-детекция = НЕ этот пак (упирается в L3-спеку). Дизайн проверь мысленным тестом archaic-register: второй лейбл добавляется данными? - B2. Маршрутизация ролей под лейблом. Переводчик adult-контента = Mistral (D19 — ровно так). Редактор — открытый вопрос: dspro НЕЛЬЗЯ (без capability), кандидаты — mistral-large/glm/grok; предложи с аргументами (глоссарий/проза/цена; эмпирики нет — честно скажи, что выбор интерим до замера). Эскалация — цепочка лейбла (
chains.adultуже в конфиге). Судья — eval-сторона, НЕ в паке (D22.6 проба-гейт у полигона). - B3. Refusal-политика цепочки (GENERIC). Сегодня refusal → flag+skip; спроектируй per-chain политику: отказ ЛЮБОЙ причины → следующий хоп цепочки лейбла до потолка → flag+skip; потолки/бюджет; как ложится в существующую лестницу regenerate→escalate (семантику не менять молча). Никаких «18+ отказов» как отдельного класса.
- B4. Механическая гарантия маршрутизации. Enforcement «label ⊄ capability → не отправлять»: загрузка конфига (fail-loud на модели без способности в цепочке лейбла) + рантайм-ассерт перед вызовом. Тест обязателен обоим.
- B5. Wire/снапшот/резюм. Channel-маркировка фолдится в снапшот (какую волну двигает)? Чекпойнты/RequestHash adult-вызовов — штатно; no-adult путь байт-идентичен; фикстуры синтетические.
- B6. Отчётность. Канал в паспорте главы/quality-report/леджере (CostSource-атрибуция adult-вызовов) — что дёшево сейчас, что в очередь.
Приёмка фазы 1: отчёт docs/archive/reports/PACK17_DESIGN_<дата>.md — НАЧИНАЕТСЯ эхо-блоком (≤10 строк: скоуп/инварианты/не-делать); по каждому B: варианты, рекомендация, риски; адверсариальный селф-ревью (линзы: L3-линия/гардрейлы · маршрутизация-fail-loud · байт-точность канала A · деньги/резюм · общность §0). СТОП — ратификация.
ФАЗА 2 — СТРОЙКА (ратифицировано D39.26; читай вместе с §14 отчёта — там file:line на каждый пункт)
Читать перед работой: §14 отчёта фазы 1 (несущее) + D39.26 в 05-decisions-log.md (что я изменил против §14 и три добора приёмки). Промт даёт РЕШЕНИЯ; код-факты вытаскивай сам, отчёт — карта.
«РОВНО ТАК» (ратифицировано; отступление = пинг оркестратору через владельца, не тихая девиация)
- Лейблы НЕ входят ни в один хеш. Назначенный слой снапшота (разрядка D20.2-Q3) = резолвнутая модель стадии + её wire-фолд, пер-стадийно и пер-волново (
stageSnap): лейбл на редакторе двигает ТОЛЬКО edit-волну, оплаченный драфт резюмится за $0. Канон brief ЗАМОРОЖЕН —"adult":falseостаётся 7-м полем, omitempty-хвост НЕ нужен;stageSnap.Escalate*сохраняют имя/тег/позицию/правило заполнения, любой фолд хопов — строго аддитивный указатель+omitempty. Провенанс лейблов — шапка отчёта, не хеш. - Порядок: РЕЗОЛВ → ВАЛИДАЦИЯ → все читатели видят резолвнутое. Лейблы приходят в
LoadPipelineтем же швом, чтоpair(доктрина «все проблемы конфига одним списком»); резолвнутые поля —yaml:"-"; «достижимое» ЛЕЙБЛ-ЗАВИСИМО (st.EscalateTo/chains.defaultпод лейблом недостижимы); дедуп — только по цепочкам активных лейблов ИСПОЛНЯЕМОГО конфига (C2-заглушка не блокирует загрузку); резолв работает и на read-путях (export/statusпере-считывают снапшот). - Эскалация под лейблом = ОДИН хоп
chain[0](Q4 = B3-A′):len(chain) > 1— громкая ошибка загрузки «мульти-хоп не построен» (тихого усечения нет);escalation.budget_usd > 0ОБЯЗАТЕЛЕН для route-лейбла (иначе гейт не может выстрелить);escMu— как сегодня (лок-на-итерацию ОТМЕНЁН: он ломает пин «перерасход ≤ 1 хоп»). - Гранулярность v1 = КНИГА (аргумент гарантии: авто-скрина нет, пер-главность сводит ToS-гарантию к точности ручного чтения).
labelsFor()— БЕЗ аргумента, с ассертом книго-константы; диапазоны глав НЕ обещать формой. - Вокабуляр данных: книга —
content_labels:, провайдер/модель —accepts_labels:(разные ключи: свойство контента ≠ разрешение получателя); пер-модельный оверрайд —*[]string, только СУЖАЕТ (nil = наследовать, указатель на пустой = «ни одного», модельный ⊆ провайдерского, load-тест на вычитание); реестр политик — УПОРЯДОЧЕННЫЙ СПИСОК (action: route|terminal), «первая политика, претендующая на стадию, выигрывает», равное притязание = громко; лейбл книги без записи в реестре = громко; эффективный список хопов — упорядоченное объединение с дедупом ПОСЛЕ резолва. - Отставки — ОДНИМ диффом:
permissive(громко при наличии) ·adult:книги (громко ТОЛЬКО наtrue;false/отсутствие терпимо — ключ несут 13 файлов вне git +example/book.yaml; обязателенLoadBook-тест на все три формы) ·Stage.Channel+ его enum + блок изоляции D4.1 (иначеproviderPermissiveвечно false и выжившийchannel: adult= операторский тупик) ·CheckAdultChannel. Go-идентификаторы — БЕЗ слова adult (тег = замороженный ключ данных). Два существующих adult-теста перепиши/удали тем же диффом. - Механическая гарантия: инвариант «для книги с набором лейблов L каждая модель, которую прогон может вызвать, несёт все лейблы L». Рубеж 1 — загрузка (сообщение называет модель, провайдера и НЕДОСТАЮЩИЙ лейбл). Рубеж 2 — рантайм-ассерт в
runAttemptДОReserveчерезclientFor(model, labels)(компиль-энфорс: путь на провод не может не объявить контент). Ассерт НЕ переносить доGetCheckpoint(реплей ничего не отправляет; перенос отнял бы $0-реплей). Негативный тест — на СВЕЖЕМ вызове, ассертит идентичность ОШИБКИ, не дельтуspend. - Отказы загрузки — за
forWrite; резолв — ВСЕГДА. Книга, помеченная после оплаты, обязана остаться читаемой ($0 read-only, D20.4) — иначе единственный выход «снять лейбл» = тихий обход; на read-пути те же условия дают громкое предупреждение + флаг в шапке отчёта. internal/llm/failover.go— УДАЛИТЬ (вызывающих нет; пересылает тот же запрос другому провайдеру — ровно то, что лейбл запрещает; nil-panic-дыра D4 п.1). Тесты файла уходят с ним — объявить в цензе^func TestИСПОЛНЕНИЕМ. Гард-тест шва оставить:\.Complete(внеinternal/llmи внеstagerun.go— пусто, с ИМЕНОВАННЫМ аллоулистомlive_conformance_test.go.- Реестр-пример — только
routeна синтетическом значении.prohibitedиз примеров убрать (не воспроизводить выходы будущего L3); механизмterminalпостроить, значение НЕ заводить; будущий L3-скрин подключается НАЗВАННЫМ пер-лейбловым хуком политики, а не черезterminal. D22.7 этим паком НЕ снимается — пер-чанковый L3-скрин остаётся предусловием первой erotica-книги в проде. - Отказ РЕДАКТОРА под лейблом терминален (D12 pinned: flag+skip без хопа). Refusal остаётся причино-агностичным: новых классов нет,
refusal.txtне переписывается. - Закрыть тихий выход
reasoning:"off"на аддитивном провайдере (добор приёмки B). Сегодня гейтpipeline.go:541гейтится внешнимst.Reasoning != "off", а шиппинг-стадия edit объявляет ровноoff(no-op для dspro, НО не для grok:control: effort, off_effort: noneшлёт явныйnone) ⇒ деньги честны, а эхо-зона D19.1 п.2 («reasoning-off + плотный CJK — свойство класса, DeepSeek и ОБА grok-слага») открыта, иechoMineViolationвыстрелить не может (echoes_when_thinking_offтолько у deepseek). Форму выбираешь сам и аргументируешь (данные: флаг у xai ⇒offстановится громким | код: аддитивный гейт над резолвнутой моделью независимо отoff), закрытие — обязательно, с тестом. - Рейт-гарды утверждать ПОЗИТИВНО (добор C):
rateGuard()возвращает nil (= без лимита) молча, в отличие от громкогоr.client; лейблованный переводчик —mistral-large-2512сmax_concurrency: 2. Тест: резолвнутая лейблованная модель получила свой гард. - Тесты (все обязательны, правило 11 — гоняем, не читаем): негативный load (книга с лейблом + модель без способности) · рантайм-ассерт до резервации · сквозняк refusal→хоп→OK→ре-гейт · сквозняк «хоп тоже отказал» → flag+skip · генеральность на СИНТЕТИЧЕСКОМ значении лейбла (если движок знает слово «adult» — тест красный) · второй лейбл только данными · шиппинг-конфиги в лейблованном сценарии.
- Док-правки §10 отчёта (5 расхождений док↔код) — тем же паком, включая устаревшие против D30.1 комменты про «вход редактора — русский черновик».
«РЕШИ САМ И АРГУМЕНТИРУЙ»
- Форма закрытия п.12 · где физически живут резолвнутые поля и как именно
labelsForдоезжает доrunAttempt· формы валидационных сообщений · отчётность B6 (шапкаreport/statusс резолвнутыми лейблами и таблицей маршрутизации ·Hopsиз durable-чекпойнтов · read-only агрегатSpendByModel) — состав и объём на твоё усмотрение, миграций схемы НЕ вводить,Roleсинтетическую под лейбл НЕ заводить (осьRequestHash= новый платный вызов). - Данные редактора/переводчика под лейблом НЕ прибивай сам: переводчик =
mistral-large-2512(D19, ровно так); редактор и вокабуляр лейблов ждут владельца (единыйadultпротивviolence/sexually-explicit— D14 п.1 оставляет DeepSeek допустимым на violence; кандидаты редактора только из способных, dspro запрещён на sexually-explicit по ToS, mistral отвергнут как несущий D39.20, glm-5 — одна строка данных ТОЛЬКО после сверки ToS/AUP Z.AI по первоисточнику). Строй механизм так, чтобы ответ был строкой данных; получишь его релеем.
ВЫНЕСЕНО ИЗ ПАКА (не делать)
escalation_model = ОТВЕТИВШАЯ модель (вердикт-изменение: golden пинит esc_model на отказавшем хопе ⇒ отдельная ратификация с санкционированным пере-капчером) · --accept-rebill (D20.2-Q2, открытая петля) · полный обход цепочки · авто-детекция лейблов · L3-классификатор · судья 18+ (eval-сторона).
Хвосты общности из петель — УСЛОВНО: Detail-строки чекеров из данных · множитель ×2 lintTimeUnits (checkers.go:174) → ключ данных. Берутся ТОЛЬКО в байт-нейтральной форме (данные в пар-конфиге, фолд лишь при отличии от дефолта) с доказательством ИСПОЛНЕНИЕМ (выход чекеров байт-идентичен до/после над корпусом); иначе CheapGateVersion/pack.Version() двигают снапшот стендовых книг и убивают $0-резюм драфта под замер остатка пака-16 — тогда отложи и скажи явно. Молча bump-нуть версию нельзя, молча не bump-нуть — тоже.
Инварианты фазы: golden байт-идентичен без пере-капчера · парити EXACT · -race · сэндбокс-репродукции через настоящий драйвер (правило 11: mock-провайдер, сквозные сценарии — refusal-каскад, реджект неспособной модели, маршрутизация) · дифф ^func Test ИСПОЛНЕНИЕМ, не памятью · заявление = команда (приёмка ре-ранит манифест) · самопроверка ревью исполнением своего кода и результатов · сессия НЕ коммитит, git mv декларировать.
НЕ делать
L3-классификатор · live 18+ вызовы без санкции · реальный 18+ текст в репо/фикстурах · копирование GPL/AGPL · пар/книго-литералы и провайдер-литералы в Go · расширение скоупа без пинга.
Приёмка (мандат 12.07 + нормы 7–11)
Фаза 1 — СТОП после отчёта. Фаза 2 — отчёт docs/archive/reports/PACK17_CHANNEL_B_REPORT_<дата>.md; сессия НЕ коммитит; git mv декларировать.