34 KiB
Отчёт бэкенд-сессии: ПАК-18 «долги контракта» (25.07.2026)
Ревью-шапка оркестратора №8 (25.07, приёмка execute-first, инлайн; ПРИНЯТ —
D39.31). 0 блокеров. Ре-ранил сам: build/vet чисты ·gofmt— толькоinternal/llm/llm.go, воспроизводится на HEAD (файл не трогали) ·-race12/12 ·-shuffle=onзелёный · парити EXACTn=13618 … 0.9655 (56/58)· ценз диффом ИМЁН 455→475, удалено 0. Санкционированный пере-капчер проверен МАШИННО: замаскировалesc_model="…"в HEAD-версии и в рабочей — файлы байт-идентичны;brief_hash, обаsnapshot_*_payload,memory_versionсовпадают построчно ⇒ вердикт-изменение не утащило ни одной другой оси, пере-оплаты нет. Сдвинулись ровно 4 строки, всеch3/0 draft. Новый baseline golden —211c9013…089045d6. Мои независимые мутации (не из списка сессии), обе пойманы: формула порогаmin→max→ красныйTestRebillConsentThresholdFormula+ пять смежных, включая оба CLI-провода; в проекцию пущены строки, резюмящиеся за $0 (завышение суммы под подпись) → красные триTestRebillProjection*. Развилка «--resnapshot≠ согласие» — принята и даже не является девиацией: спека прямо говорит «отдельный от--resnapshot-алиаса» (backend/docs/D15.2-content-addressed-resume-spec.md:590); аргумент сессии сверх того верен — при алиас-прочтении ратифицированный порог становится гейтом, который не может выстрелить. Отсрочка п.3 принята как ИЗМЕРЕННАЯ:pack.Version()a7d4be2c0465→133d71e8d132, стендовая книга объявляетlangpack_rootровно на репозиторный каталог (проверил/home/ubuntu/books/gu-zhenren/rerun2/book.yaml); определительный аргумент по Detail-строкам (дефолт шаблона обязан рендерить текущую строку ⇒ литерал остаётся в Go) принят — байт-нейтральной формы у этого нита не существует. Оба нита едут на ближайший полный--resnapshot. Дефект честности, найденный сессией у себя (проекция считала строки-сироты и завышала сумму под подпись), — правильного класса; зафиксирован нормой в D39.31 п.3.
Промт: docs/BACKEND_PACK18_DEBTS_SESSION_PROMPT.md (оркестратор №8, выдан 25.07).
Итог: пункты 1 и 2 ПОСТРОЕНЫ и проверены исполнением; пункт 3 ОТЛОЖЕН с доказательством
исполнением, что байт-нейтральной формы не существует (принятый промтом исход).
Сессия не коммитила. git mv не выполнялось. Платных вызовов — ноль.
Аддендумы: за время сессии релеем не приходило ни одного (строка-подтверждение по требованию промта).
Эхо-блок (сверка со скоупом, выдан ДО работы)
Скоуп: --accept-rebill[=usd] на снапшотной гранулярности · escalation_model = авторитетная модель ·
два нита общности УСЛОВНО. Инварианты: согласие ДО денег · golden байт-идентичен кроме санкционированного
пере-капчера п.2 (только колонки esc_model) · ни одна ось RequestHash/снапшота не двигается ·
CheapGateVersion/pack.Version() не двигаются · общность §0 · $0-контракт read-only путей.
Не делать: guard_hash/пер-чанковый dry-run · ru-target долг · accepts_labels · L3 · live 18+ ·
миграции durable-строк · расширение скоупа без пинга.
ПУНКТ 1 — --accept-rebill[=usd]: согласие на пере-оплату. ПОСТРОЕН
Что построено
Новый файл backend/internal/pipeline/rebill.go (единственное место логики) + проводка:
| Файл | Что |
|---|---|
internal/pipeline/rebill.go |
RebillConsent, RebillProjection, projectRebill, projectBookUSD, rebillConsentThreshold, checkRebillConsent |
internal/pipeline/runner.go:52 |
поле AcceptRebill RebillConsent (ортогонально Resnapshot) |
internal/pipeline/bookrun.go:137 |
гейт в TranslateBook — после seedGlossary+SplitChunks, ДО волн (значит до первой Reserve) |
internal/pipeline/status.go:682 |
гейт в Redrive — ДО деструктивного ResetChunkStages |
internal/pipeline/status.go:485 |
ProjectedBookUSD вынесен в общий projectBookUSD (одно определение на порог и на status) |
internal/config/book.go:100 |
rebill_consent_usd — переопределение порога книгой (0 = ратифицированный дефолт) |
cmd/tmctl/invocation.go |
--accept-rebill[=usd] через flag.Value+IsBoolFlag |
cmd/tmctl/main.go |
проводка в translate и redrive |
Формула (ратифицированная, D20.2-Q2): порог = min($0.50, 5%×ProjectedBookUSD), при
ProjectedBookUSD = 0 — абсолютный флор $0.50. Книга может переопределить (rebill_consent_usd).
Проекция (снапшотная гранулярность): Σ chunk_status.cost_usd по строкам, которые
(а) несут снапшот, (б) были ОПЛАЧЕНЫ (ok/flagged; skipped не доезжал до провайдера), (в) чей
снапшот ≠ текущему снапшоту ЕГО ВОЛНЫ, (г) чьи стадия и позиция ещё существуют.
«РЕШИ САМ И АРГУМЕНТИРУЙ» — мои решения
1. Где живёт вычисление. Прайор промта принят: рядом со status-проекцией, но с уточнением —
ProjectedBookUSD вынесен из Status в общую функцию projectBookUSD (rebill.go), которую
теперь зовут ОБЕ стороны. Причина: порог = 5% от этого числа; порог, посчитанный от второй,
дрейфующей копии той же величины — ровно тот класс, ради которого в паке-16 выносили memberDrops.
Вынос доказан байт-нейтральным исполнением (golden и status-тесты зелёные без правок).
2. Форма сообщения об отказе. Несёт: сумму (6 знаков), число единиц (chunk×stage), порог И его
происхождение (5% от проекции $X / флор $0.50 / book.rebill_consent_usd), строку
«NOTHING was reserved and no row was touched», и точную команду-лекарство. Отдельная форма для
превышенного потолка (--accept-rebill=1.50 при проекции $2.41). Когда --resnapshot не передан,
добавляется хвост «run also needs --resnapshot» — оператор получает ОБА флага сразу.
3. Как флаг ложится на translate и redrive — ЭТО РАЗВИЛКА, РЕШЁННАЯ МНОЮ, ОТМЕТЬТЕ ПРИ ЛЕНДИНГЕ.
Спека §7.3 говорит: «--resnapshot остаётся алиасом-синонимом (семантика — прими проецируемый
re-bill)». Я это НЕ перенёс. Флаги сделаны ортогональными: --resnapshot = разрешение
пере-пиннить, --accept-rebill = согласие на СУММУ; сверх порога нужны оба. Аргументы:
- оговорка спеки живёт в §7 «Что демонтируется» — в мире, где fail-loud снапшот-гейт УДАЛЁН и
--resnapshotиначе теряет смысл. Гейт не демонтирован (guard_hashне строим), поэтому у--resnapshotосталось своё живое значение; - при алиас-прочтении ратифицированный порог становится мёртвым кодом: на пути
translate--resnapshotтребуется в любом случае и сам же был бы согласием — порогу нечего гейтить. Ортогональность — единственное прочтение, при которомmin($0.50, 5%×…)вообще что-то делает; - Р6 = согласие на КОНКРЕТНУЮ трату. Флаг, чьё имя и help-строка не упоминают денег, её не несёт;
а долг сформулирован в трекере ровно так: «
--resnapshotпере-пиннит без суммы»; - направление строго безопасное: ни один прогон, который раньше отказывал, теперь не проходит; часть прогонов, которые раньше проходили, теперь останавливаются с напечатанной суммой.
Цена решения (честно): 4 существующих теста, гонявших --resnapshot в одиночку, получили строку
AcceptRebill = RebillConsent{Given: true} (перечислены ниже). Это и есть смена контракта.
4. Проекция ниже порога. Прайор промта принят — продолжаем. Но не молча-невидимо: сумма и число
единиц уходят в лог (Info, «continuing without asking»). Деньги обязаны быть видны, даже когда не
спрашивают.
5. Потолок ниже порога. Именованный потолок honoured всегда, даже когда проекция ниже порога:
--accept-rebill=0.001 — это инструкция, а не форма согласия. Оператор, написавший «не больше $X»,
не должен быть оплачен на $X+ε на том основании, что сумма была мелкой.
6. Ловушка stdlib (найдена исполнением, а не чтением). IsBoolFlag — единственный способ дать
флагу опциональное значение, но тогда --accept-rebill 1.50 (через пробел) не связывает сумму:
флаг читается голым, 1.50 становится бесхозным аргументом, и потолок молча превращается в
безлимитное согласие. Это отказ с показом правильного написания. Отказ прицельный (только при
голом флаге + бесхозный аргумент) — исторически терпимый бесхозный аргумент везде ещё терпим
(запинено тестом).
Граница скоупа — фиксирую строками, как требует промт
- Каскад §7.1-бис на снапшотной гранулярности ВЫРОЖДЕН. Пере-оплачивается вся волна целиком, поэтому правило «стадия строго ниже re-bill-единицы сама считается re-bill» не добавляет ни одной единицы. Ратифицированный порядок «каскад ложится ПЕРЕД семантикой флага» не нарушен — он неприменим.
- Ветка
EstimateUSDиз §7.2 не построена, и у неё здесь нет предмета. Она существует для каскадных downstream-единиц без прошлой цены; на снапшотной гранулярности каждая учтённая единица ИМЕЕТ хранимую цену — именно за то, что была оплачена. Оплаченная строка сcost_usd = 0— это честно $0-модель (local/нулевой прайс), и её вклад $0 верен, а не пробел. Строить мёртвую машинерию (least mechanism) не стал. - Развилки «снапшотной гранулярности недостаточно» не возникло — пинг не потребовался. Проверено
по коду: под
--resnapshotfast-pathchunk_statusтребуетcs.SnapshotID == snapID(stagerun.go:86), промах ⇒ attempt-цикл ⇒RequestHashнесётSnapshotID⇒ промах чекпоинта ⇒ свежий платный вызов. То есть каждая оплаченная строка под чужим снапшотом действительно пере-оплачивается — сумма честна, а не консервативна. - НЕ покрыто (документировано, не умолчано): КОНТЕНТНАЯ ось. Правка исходника, не сдвинувшая
манифест, меняет
content_hashчанка, но не снапшот — она пере-оплатит ровно тронутые чанки и в проекции невидима. Это та же оговорка, что несётstatus.bookChunks(status.go:169-175), и половина content-addressed resume v3, а не этого гейта.
Дефект, найденный МОИМ ревью собственного кода (и починенный)
Первая редакция считала строки-СИРОТЫ: позиции, исчезнувшие из манифеста (исходник укоротили) и
стадии, которых в пайплайне больше нет. Их никто не пере-запустит ⇒ проекция завышала сумму, под
которой просят подпись. Завышение — безопасное направление, но число, которое просят одобрить и
потом не тратят, — это ровно то, отчего такие числа перестают читать. Обе сироты исключены,
обе запинены тестами (TestRebillProjectionIgnoresVanishedChunks, …IgnoresRetiredStages) и
мутациями M16/M17.
ПУНКТ 2 — escalation_model = модель, чей выход АВТОРИТЕТЕН. ПОСТРОЕН
Прайор промта принят целиком, альтернативы не приношу — аргумент «терять идентичность отказавшего
хопа нельзя» проверен и не подтвердился: идентичность НЕ теряется. Отказавший хоп сохраняет
(а) собственный durable-чекпоинт под своим request_hash на модели хопа, (б) собственную строку
request_log с model_requested=fake-fallback и degraded=hard_refusal. Проверено исполнением:
в golden секция request_log при пере-капчере не изменилась ни одной строкой, а тест
TestRunnerEscalationFallbackAlsoFailsFlags теперь явно считает эту строку.
Правка: stagerun.go:158-193 — escalated = true выставляется при любом состоявшемся хопе
(деньги/телеметрия), escModel — ТОЛЬКО когда выход хопа стал авторитетным (last = esc.fb, т.е.
хоп прошёл ре-гейт или дал косметический sanitizer_stripped, который отгружается).
Миграции нет, старые строки не переписываются. Смешанная семантика в исторических данных
допустима и записана в durable-месте, где её увидит следующий читатель: доккоммент поля
store.ChunkStatus.EscalationModel (internal/store/chunkstatus.go:35-43) несёт и новую семантику,
и абзац «HISTORICAL MIXTURE (pack-18, deliberate — no migration)».
В tmctl report баннер НЕ добавлял — аргумент. escalation_model не печатается ни одной
поверхностью CLI (проверено грепом: потребители — только stagerun/resume/store/golden;
render.go печатает Escalations: N, а не модель). Отличить старую строку от новой в данных
нечем — маркера нет. Значит баннер был бы безусловным и неактивируемым текстом, который ничего не
говорит оператору о конкретной строке. Место факта — схема (сделано) и D-лог.
Пере-капчер golden — дисциплина приёмки выполнена
TM_UPDATE_GOLDEN=1 go test ./internal/pipeline/ -run TestGolden
Маскированный структурный дифф (Ш-1), напечатанный ДО записи:
golden masked-diff (Ш-1): 8 verdict/wire change line(s), 0 version-only line(s)
~ stage=draft … disp=flagged flag="hard_refusal" … escalated=true esc_model="" finish="refusal" …
~ ch3/0 draft … disp=flagged flag="hard_refusal" … escalated=true esc_model="" detail="provider finish_reason=refusal"
~ stage=draft … resume=true … escalated=true esc_model="" finish="" …
~ ch3/0 draft … escalated=true esc_model="" detail="provider finish_reason=refusal"
Сырой дифф файла: 4 удалённых / 4 добавленных строки, все на ch3/0 draft — единственном хопе
фикстуры, который ОТКАЗАЛ. Проверено машинно (не глазами): скрипт заменил esc_model="…" на
плейсхолдер в обеих сторонах каждой пары и сравнил — only esc_model columns moved: True.
Ни одной другой сдвинувшейся строки ⇒ стоп-условие промта не сработало.
Ни одна ось RequestHash/снапшота не двинулась — доказано исполнением:
snapshot_draft: HEAD vs worktree — IDENTICAL
snapshot_edit: HEAD vs worktree — IDENTICAL
brief_hash: IDENTICAL
memory_version: IDENTICAL
base_memory_version: IDENTICAL
плюс в самих изменённых строках content_hash/final_hash/cost побайтно те же; секции
request_log, retrieval_state и wire bodies в диффе отсутствуют вовсе. Пере-оплаты нет.
Golden: f7641993…4f0020f8 → 211c9013f5cfa31562857cc9518488393a647cce489d37113402b159089045d6.
testdata/ в остальном чист (git status показывает только capture.golden).
ПУНКТ 3 — два нита общности. ОТЛОЖЕНЫ (байт-нейтральной формы не существует)
Промт: «берутся ТОЛЬКО в байт-нейтральной форме… Если не выходит — отложи и скажи явно с причиной; это принятый исход». Не вышло. Причина измерена, а не предположена.
Замер (throwaway-проба в песочнице, репозиторий не тронут)
Собрал книгу с langpack_root (как боевые стендовые), снял оба волновых снапшота, дописал в копию
configs/langpacks/zh-ru/dc-checkers.txt одну строку (pattern\tshichen_hours\t2), пересобрал:
PROBE pack.Version(): langpack-v2-a7d4be2c0465 → langpack-v2-133d71e8d132 moved=true
PROBE snapshot_draft: c4e204b020bbc550437aa567 → a234e731ebabb78ec12dc6d1 moved=true
PROBE snapshot_edit: 84abf42f15c9df7f0cf22a2b → 7c712192ada86df74a0b3b7e moved=true
a7d4be2c0465 — та самая версия пака, что записана в PROGRESS за пак-16. Двигаются ОБЕ волны
(LangpackVersion фолдится в общем билдере buildSnapshotID, snapshot.go:428, который зовут обе).
Кого это убивает: стендовые книги ссылаются langpack_root ровно на этот каталог репозитория —
/home/ubuntu/books/gu-zhenren/rerun2/book.yaml:23, book-dspro.yaml:22, book-mistral.yaml:22.
То есть любая правка данных пары стирает $0-резюм ДРАФТА, на котором должен поехать замер остатка
пака-16.
Почему закрыты и остальные двери
| Дом данных | Итог |
|---|---|
langpack (dc-checkers.txt) |
версия = sha256 БАЙТОВ файла ⇒ любая новая строка двигает оба снапшота. Замерено выше. |
пар-слой configs/pairs/<пара>.yaml, фолдится |
новое поле с значением ⇒ payload снапшота меняется ⇒ тот же класс. |
| пар-слой, НЕ фолдится | тихо снимает версионирование с правила, которое CheapGateVersion версионирует БЕЗУСЛОВНО (snapshot.go:432; checkers.go:27 прямо: «Version rides the langpack Version() (data) + CheapGateVersion (algorithm)»). Это вторая половина запрета промта: «молча НЕ бампить, поменяв версионируемое правило, — тоже [нельзя]». |
пар-слой, фолдится через omitempty, zh-ru НЕ шлёт ключ |
байт-нейтрально — но тогда «2» остаётся в Go как молчаливый дефолт для любой пары, что шлёт DC1-паттерны без коэффициента. Утечка не устранена, а раздвоена на два дома — против принципа, который этот же файл декларирует про hourWordRE («how this target renders the double-hour is one fact with one home», checkers.go:53-56). |
Для Detail-строк ограничение ещё жёстче и является определительным: байт-нейтральность ТРЕБУЕТ, чтобы дефолт шаблона рендерил ровно текущую строку — то есть 时辰-литерал обязан остаться в Go дословно. Нит про Detail-строки байт-нейтрально нереализуем в принципе, а не по обстоятельствам.
Ничего в internal/checks/ не тронуто: CheapGateVersion и pack.Version() не двигались,
golden не трогался этим пунктом, парити EXACT воспроизведена.
Готовый план на момент, когда снапшот и так поедет (одним шагом, ~час)
Пять Go-сайтов, все в двух файлах (перечислены грепом, не памятью):
- множитель:
checkers.go:174(expectedHours := n * 2),repair.go:124(ruNum == n*2),repair.go:138(~%d h,n*2),repair.go:392(newNum == oldNum*2); - 时辰-текст:
checkers.go:153,checkers.go:176,repair.go:103,repair.go:138.
Форма: новые ключи в configs/langpacks/<пара>/dc-checkers.txt — unit_hours (коэффициент) и
dc1_detail / dc1_fractional_detail (шаблоны с подстановками {n}/{got}/{want}/{word},
без англ. диагностики в теле). Fail-loud, а не дефолт: пара, что шлёт shichen_re без
unit_hours, обязана падать на загрузке — иначе вторая пара молча получит «2». Версионирование
приезжает даром: байты файла уже в pack.Version().
Два кандидатных слота (решение — оркестратору/владельцу): (а) вместе с включением платной петли
ремонта (D39.24) — она и так двигает снапшот шиппинг-волны, но НЕ драфтовой, так что правка пака
добавит пере-оплату драфта; (б) на ближайшем полном --resnapshot стендовых книг — тогда бесплатно
целиком. Слот (б) чище.
Самопроверка ИСПОЛНЕНИЕМ (мандат владельца 12.07)
Манифест приёмки — заявление = команда (каждая ре-ранится)
cd backend
go build ./... # ok
go vet ./... # ok
gofmt -l . # internal/llm/llm.go — ВОСПРОИЗВОДИТСЯ НА HEAD (git show HEAD:… | gofmt -l), сессия файл не трогала
go test ./... -race # 12 пакетов ok, 0 FAIL
go test ./... -shuffle=on # 12 пакетов ok, 0 FAIL
sha256sum internal/pipeline/testdata/golden/capture.golden
# 211c9013f5cfa31562857cc9518488393a647cce489d37113402b159089045d6
TM_MINER_PARITY=1 go test ./internal/miner/ -run TestMinerFullBookParity -v
# PARITY: n=13618 catastrophe{方源:0 蛊:1 蛊师:2 古月:22} recall@proposed=0.9655 (56/58 GT) — тождественно пакам 15/16/17
grep -rh "^func Test" --include=*_test.go . | sed 's/(.*//' | sort # ценз ДИФФОМ ИМЁН
Ценз тестов исполнением (диффом имён, не счётчиком): 455 → 475, удалено 0. Добавлено 20:
15 в internal/pipeline (rebill_test.go ×13, runner_test.go ×1 новый + 1 усиленный),
4 в cmd/tmctl (invocation_test.go ×3, rebill_cli_test.go ×2).
Изменённые существующие тесты (не удалённые — по строке AcceptRebill каждый)
TestRunnerSnapshotPinning · TestRunnerMemoryResnapshotOnApprovedChange ·
TestRedriveResnapshotAcceptsDrift · TestWaveMinedSignDoesNotRebillDraft — все четыре гоняли
--resnapshot в одиночку и теперь несут явное согласие. Это прямое следствие решения №3 выше и
единственное место, где пак сменил поведение существующих сценариев.
TestRunnerEscalationFallbackAlsoFailsFlags дополнен тремя ассертами (не переписан).
Сквозные сценарии через НАСТОЯЩИЙ драйвер (норма 11)
Согласие сверх порога · согласие под порогом (через rebill_consent_usd) · отказ без флага ·
--accept-rebill=<сумма> ниже проекции и выше неё · хоп ответил · хоп отказал · read-only живы ·
redrive до сброса · redrive --dry-run · пер-волновая проекция на mined-sign · $0-резюм не спрашивает.
Все — через TranslateBook/Redrive/translate()/redrive() над мок-провайдером; отказные
сценарии проверяют не только текст ошибки, но число вызовов провайдера, committed/reserved и
неизменность durable-строк.
Мутационный рубеж: 19 мутаций в КОПИИ дерева, 19 красных, 0 выживших
| # | Мутация | Красный тест |
|---|---|---|
| M1 | гейт отключён целиком | RefusesOverThreshold, Cap, ReadOnlyPathsAlive |
| M2 | skipped-строки считаются |
ProjectionExcludesSkipped |
| M3a | edit-строки судятся по драфт-снапшоту | ProjectionIsPerWave, IgnoresRetiredStages |
| M3b | draft-строки судятся по edit-снапшоту | ProjectionIsPerWave, ExcludesSkipped, IgnoresRetired |
| M4 | потолок игнорируется | CapBelowProjectionRefuses |
| M5a | порог min→max |
ThresholdFormula |
| M5b | флор $0.50 снят при нулевой проекции | ThresholdFormula |
| M5c | rebill_consent_usd игнорируется |
UnderThreshold, ThresholdFormula |
| M6 | согласие в redrive ПОСЛЕ сброса | RedriveRefusesBeforeDestructiveReset |
| M7a | экстраполяция убрана | ProjectBookUSDExtrapolates |
| M7b | знаменатель processed→total |
ProjectBookUSDExtrapolates |
| M7c | flagged-единицы вне базы | TestStatusAndRedrive |
| M8 | read-only status зовёт гейт |
ReadOnlyPathsAlive |
| M9 | гард пробельной формы снят | ParseAcceptRebillSpaceFormRefused |
| M10 | отрицательный потолок принимается | ParseAcceptRebillRejectsBadCeiling |
| M11a | согласие не проводится в раннер (translate) | TranslateWiresAcceptRebill |
| M11b | потолок теряется при проводке | TranslateWiresAcceptRebill |
| M12 | сравнение с потолком ослаблено | CapBelowProjectionRefuses |
| M13 | согласие не проводится (redrive) | RedriveWiresAcceptRebill |
| M14 | esc_model обратно = ПОПРОБОВАННАЯ |
GoldenDeterminism + EscalationFallbackAlsoFails |
| M15 | esc_model не ставится никогда |
Golden + FixesEcho + SurvivesResume |
| M16 | строки исчезнувших чанков снова считаются | ProjectionIgnoresVanishedChunks |
| M17 | live-множество инвертировано | RefusesOverThreshold, Cap, IsPerWave |
Две мутации СНАЧАЛА выжили и вскрыли дыры в моих же тестах — обе закрыты, а не списаны:
- M3 (пер-волновая ось) — первая формулировка мутации была ненаблюдаемой; переформулировал в обе
стороны и обнаружил, что «чистая книга не проецирует пере-оплату» не ассертилось нигде. Добавил
этот ассерт в
TestRebillProjectionIsPerWave— теперь обе стороны красные. - M11 (проводка CLI) — ни один тест не проверял, что распарсенное согласие ДОЕЗЖАЕТ до раннера.
Это буквально регресс-класс D20.4 («
--resnapshotпарсился и молча игнорировался»), который в этом репозитории уже случался. Написанcmd/tmctl/rebill_cli_test.go, гоняющий настоящиеtranslate()/redrive()над мок-провайдером.
Что осталось / вопросы оркестратору
- Ратифицировать девиацию от алиас-оговорки §7.3 (решение №3 выше):
--resnapshotи--accept-rebillортогональны. Если оркестратор захочет алиас-семантику — это одна строка вcheckRebillConsent, но тогда ратифицированный порог становится мёртвым. - Проекция в
tmctl statusНЕ добавлена — сознательно (скоуп). Спека §9 предлагает заменить булевConfigDriftчислом «N чанков, ~$X»; на снапшотной гранулярности это дёшево иomitemptyоставило бы JSON байт-идентичным для недрейфующей книги. Не строил без пинга. Сегодня сумму узнают из отказаtranslate($0, без резерваций). - Пункт 3 — слот для лендинга (см. выше, кандидат (б): ближайший полный
--resnapshotстенда). - Долг ru-target (слой 7) не тронут — ждёт своего дизайн-пака, как предписано.
- Чужая зона: за время сессии параллельная сессия тронула
docs/architecture/05-decisions-log.md,docs/experiments/*,eval/README.mdи создалаdocs/archive/reports/POLYGON_TOS_LABELS_REPORT_2026-07-25.md. Не трогал ничего из перечисленного. Мои файлы — толькоbackend/**+ этот отчёт.