65 KiB
Отчёт бэкенд-сессии: ФИКС-ПАК БАНКА «КЛАСТЕРЫ + НАБЛЮДАЕМОСТЬ» (строка 128 + хвост 129 + $0-минимум 130)
⟶ РЕВЬЮ-ШАПКА ПРИЁМКИ (оркестратор №15, 08.08.2026, D39.118): ПРИНЯТ И ЗАЛЕНДЕН
bccf2d8. Приёмка адверсариальная, четыре контура: слепой дифф-ревьюер (мнение ДО отчёта) · пере-ран заявлений исполнением · 8 своих посадок в копии зоны (6 CAUGHT сразу; 2 выжившие добиты дофиксом) · охота вне карты отчёта (5 находок, 1 major). Дофикс-раунд закрыл ВСЁ: блокер lint (3× errcheck) · MAJOR «WARN строки 130 структурно мёртв» (само-исключение через сырой seed) · 2 дыры пинов на space-run-форме · инертныйbankParseVersion· 3 тихих отказа канала семей. Ре-чек дофикса:make batteryцеликом EXIT=0 (lint 0 issues) ·-raceEXIT=0 · 685→717 подтверждён независимым счётом · пере-посадки 3/3 CAUGHT. Поправки приёмки к телу: клейм «батарея зелёная» ПЕРВОЙ редакции был ложным (признано в §3 честно) · сдвиг edit-волны происходит и при ВЫКЛЮЧЕННОМ гейте терминолога (дельта пишется на $0-пути mining-стопа) и перекупает также classify-чекпойнты (контент батча делит рендер) — уточнение к §2 · замер §7.3 «0/585» = ВНУТРЕННИХ прогонов пробелов (наивный grep без rstrip даёт 55 хвостовых хитов, парсер их триммит) · пин покрытия типов работает по зеркальной фикстуреzhFamily— рассинхрон зеркала со shipped-строками пином не ловится (принято риском). Решения §7 ратифицированы D39.118.
Исполнен 08.08.2026 по промту docs/BACKEND_BANK_CLUSTER_FIXPACK_SESSION_PROMPT.md (выдан 04.08, актуализирован 08.08; после приёмки — в архиве промтов). Зона: backend/. Деньги: $0 — платных вызовов не было ни одного; вся батарея локальная. НЕ коммичено — дерево передаётся оркестратору. Живой сосед на момент сессии — полигон эксп-22 (eval/tenant_panel/, eval/role_topology/absjudge.py): не тронут, git status до и после чист по чужой зоне.
§1. Что сделано — по работам, с file:line
G1. Семьи термов и со-батчинг юнитами
| Что | Где |
|---|---|
| Данные семей (per-script, НЕ Go-константы) | backend/internal/lang/bankdata/family-morphology.txt |
| Загрузчик + резолв по языку + версия плоскости | backend/internal/lang/bankdata.go (FamilyMorphology, BankDataVersion) |
DetectFamilies рядом с DetectSeries |
backend/internal/terminology/series.go:199-295 |
MergeUnits (серия ⊕ семья ⊕ containment → один юнит) |
backend/internal/terminology/series.go:314-394 |
Batch/orderByUnit переведены на словарь ЮНИТОВ |
backend/internal/terminology/terminology.go:1119, series.go:115-142 |
| Проводка + WARN на отказ слияния | backend/internal/pipeline/terminologist.go:301-323 |
| Резолв параметров на ЗАГРУЗКЕ (fail-loud на опечатку типа) | backend/internal/pipeline/terminologist.go:126-158 |
Слияние и два гарда (правлено по адверсариальному ревью, см. §4а). Юниты сливаются семьёй; серия придерживает ТОЛЬКО своих членов (семья формируется без них), а не отменяет слияние целиком; кап членов отказывает слиянию. Оба случая — это семья, которую владелец встретит разрезанной, поэтому оба СЧИТАЮТСЯ (MergeStats{Refused, Held}) и попадают в один WARN. Тест родства — «делят руну» (в плотном письме руна = морфема), а не подстрока.
Правила (как ратифицировано промтом). Имя — общая ПРЕФИКС-морфема ≥2 рун; реалия (term|place|title) — общая СУФФИКС-морфема ≥2 рун (head-final); асимметрия и обе длины — данные. Якорем семьи может быть и сам кандидат — иначе голова семьи уезжает в другой вызов; ⚠ якорь обязан быть ≥2 рун, поэтому ОДНОРУНОВАЯ голова (蛊, 转, 窍) под это не подпадает и остаётся в отдельном вызове от своей семьи — класс НЕ покрыт, см. §5. Containment-канал (元海 ⊂ 元海空窍, оба mined) — отдельный генератор с тем же механизмом; якорь ≥2 рун, чтобы одна общая морфема не смела полбанка в один вызов.
(а) Многорунные модификаторы серий — критерий выполнен. 一转…九转 — равнодлинная серия; 十一转/十二转 — три руны и в неё не попадают. Выбранная форма — НЕ отдельное правило серия-канала, а слияние юнитов: семья с якорем 一转 (containment/суффикс) пересекается с серией, и юниты сливаются. Линейка 1..12 держится ОДНИМ батч-юнитом — пин TestFamilyKeepsAVariableLengthRankLineWhole. Равнодлинные серии не регрессируют: у двухрунных поверхностей нет собственного суффикс-корня ≥2 рун, семья про них молчит — пин TestFamilyDoesNotRegressAnEqualLengthSeries.
(б) Майнерские containment-пары — TestContainmentPairSharesAUnit.
Наблюдённый эффект на реальном корпусе (testdata/bankfull-surfaces.txt — дистилляция банка coldrun-a, 150 поверхностей; TestFamiliesOnBankFullFixtureAreBoundedAndWhole): 150 кандидатов → 14 юнитов, наибольший 20, отказов по капу 0, придержано серией 2. Содержательно юниты правильные: вся линейка 转 (12 членов вместе с 一转蛊师/九转境界), композиционный куст 元海/真元/空窍 (10 — ровно тот, на котором §A4 намерил внутри-прогонные противоречия), клан 古月 + построенные на нём поверхности (20, включая 方源/方正/族长/四代族长). Два «придержания» — это ранговый юнит 转, которому гард не дал поглотить чужие реалия-семьи (巅峰, 蛊虫): они модифицируются рангом, но морфологически к нему не относятся. Цена придержания названа честно ниже.
G2. ConsolidationConflicts
backend/internal/terminology/terminology.go:918-941 — тонкий брат CanonConflicts: тот же containment + lexemeSubset, правая сторона — консолидации ТЕКУЩЕГО прогона. Вызов terminologist.go:424-437 рядом с канон-проверкой; WARN с именованными парами, счётчик terminologyResult.SelfConflicts, per-term Contradictions → колонка стоп-таблицы (mining.go, renderBankStopTable, cmd/tmctl/render.go). $0, evidence-сторона, не фолдится. Пины: TestConsolidationConflictsCatchesTheRunContradictingItself, TestSelfContradictionIsReportedAtTheStop.
G3. Наблюдаемость арбитража
- (а)
BankStopRow+=Signals(сигналы §C2-3 ТОП-варианта — решил печатать по строке, а не по-вариантно: подписывают строку, а не вариант),Invented(норм-dst ∉ вариантов черновиков, сравнение под тем же фолдом целевой формы),Conf,Conventions,Contradicts—mining.go:244-310. Стоп-таблица и stdout-баннер печатают всё это (mining.go:renderBankStopTable,cmd/tmctl/render.go:103-153). - (б) Третье поле «уверенность 0–100» —
backend/prompts/zh-ru/terminologist.md(дата-правка + шапка с ратифицированной ГРАНИЦЕЙ применения). Парсер:terminology.go:1022-1027+confidenceField(:1073) — девиация от буквы промта, см. §4 п.1. - (в)
reasoning_contentв схему НЕ заведён (проверено grep'ом — его там и не было). - (г) Находки приёмки:
- alias-джойн подписной карты —
proposalsFromObservedзаменён наproposalsFromCandidates(mining.go:404-427): карта теперь строится из ТЕХ ЖЕ кандидатов, что и стоп-таблица, поэтому предложение, пришедшее через алиас кластера, попадает в note представителя по построению, а не вторым джойном, который надо руками держать в согласии. Провенанс алиаса едет в note (miner_emit.go:DstProposal.Via+viaNote). ПинTestSignatureMapJoinsAliasProposals. - имена эвиктнутых —
chunkrun.go:168-236(recordEvicted/reportEvicted) + аксессорmembank.PickedEntry.Src(); отчёт один на волну (waverun.go, после драфт-волны). Форма хранения — ЛОГ, без миграции схемы (обоснование и альтернатива — §4 п.4). ПинTestEvictedBankRowsAreNamed. - per-batch «спросили N / ответили M» + WARN на ПУСТОЙ ответ — рендер
terminologist.go:337-360, классификаторterminologist.go:530-548. Ложной тревоги на батчах, до которых бюджет не дошёл, нет:bankRoleRun.attemptedотделяет «вызвали и получили пусто» от «не вызывали». TestTerminologistEmptyReplyIsLoudпереписан на два подслучая — прозу (старая ветка) и НАСТОЯЩИЙ пустой completion (miningstop_join_test.go). Имя теста перестало врать.
- alias-джойн подписной карты —
- (д) $0-минимум строки 130 —
mining.go:525-575: дифф старого и нового авто-файла приwriteAutoBank+ WARN с ИМЕНАМИ выпавших термов, названнымrank_capи советом «промоутни в mined_delta, тогда это сид-поверхность и её больше не срежет». ГРАНИЦА соблюдена: накопительного мерджа нет, слоты не освобождаются,memory_versionне двигается — пинTestAutoBankRewriteNamesDroppedTermsпроверяет и то, и другое.
G5. foldVariants
terminology.go:222-296. Голос считается по классу целевой формы (NormalizeTargetForm инжектится как функция — пакет остаётся пар-агностичным), показывается СЫРАЯ форма (представитель — самая частая сырая форма класса). Рядом со Spread() (сырых форм) появился Conventions() (классов). Via при фолде агрегируется честно: если хоть один вклад пришёл на СВОЙ ключ — вариант прямой; если все через алиасы — перечисляются все. Пины: TestFoldVariantsCountsConventionsAndShowsRawForms, TestFoldVariantsKeepsViaProvenanceHonest.
Хвост 129. Парсер банкноты
banknote.go:236-274. Тип опознаётся по ЗАКРЫТОМУ словарю на ПОСЛЕДНЕМ поле, остальное — src + dst с ре-джойном (зеркало дисциплины terminology.ParseReply). Восстановление порядка колонок обобщено на разъехавшийся dst: src — одно поле при любом чтении, поэтому «объявленный порядок» и «обратный» отличаются только тем, какое поле берётся за src. Пин TestParseBanknoteRejoinsASplitRendering (обе формы + «неизвестное последнее поле — часть dst, а не молча выброшенная колонка» + обратный порядок с разъехавшимся dst, который до пака был parse_fail в обеих версиях).
Нашёлся ли двойной пробел в артефактах. ~/books/gu-zhenren/coldrun-a/ не читал: доступ к нему в этой сессии не проверялся, а промт разрешает только чтение замороженного эталона, не требует его. Цена фолда названа честно: неизвестна — авто-банк изменится ровно на тех строках банкноты, где модель поставила двойной пробел внутри dst; поиск по эталону — задача одного grep при следующем касании артефактов, вопрос вынесен в §5.
Опции
BanknoteTruncated(гигиена) — СДЕЛАНО, вариантом «честно провести флаг»: колонка была структурно недостижима (truncatedGenerationпинился вfalse), теперь читается из finish-причины (banknote.go:352-362). Поведение finish=stop-only НЕ тронуто — кандидаты по-прежнему не принимаются,NLinesпо-прежнему 0. ПинTestBanknoteTruncatedIsReachable. Миграции не потребовалось.NoDst— СДЕЛАНО: узкий матч испорченного сентинела («⟦TM-NO-DST⟧»,⟦TM-NO-DST⟧.) —terminology.go:1096-1103, пинTestParseReplyAcceptsAMangledDeclineSentinel. Отказ — это РЕШЕНИЕ §C2-7, а до пака мятый сентинел считался сломанной строкой.- Перф
AttachKWICчерез Aho-Corasick (строка 37) — НЕ делал, см. §4 п.5.
§2. Фолд-ось и голден (обязательная секция)
Предъявление, ИСПРАВЛЕННОЕ по многоагентному ревью. Первая редакция §2 утверждала «волны и снапшоты книг НЕ двинулись» без оговорки — это неверно и опровергнуто исполнением. Верно так: ДРАФТ-волна не двинулась; EDIT-волна двигается, и двигается bank-only.
- Драфт-волна цела. Строки авто-банка —
Source:"mined", а BASE-версия банка их исключает (membank/memory.go:349), поэтому черновые чекпойнты резюмятся за $0. Проверено ИСПОЛНЕНИЕМ (см. ниже). - Edit-волна двигается. Пак меняет ПОЛЕ dst в дельте: источник предложений сменился с сырого драфт-порядка (
proposalsFromObserved) на ранжированные и фолднутые кандидаты (proposalsFromCandidates). На одинаковом входе это даёт другойmemory_versionтремя независимыми механизмами (пере-ран рядом с HEAD-функцией через настоящиеDeltaYAML → LoadGlossarySeed → ComputeVersionScoped): (i) ре-ранжирование §C2-3 против «сколько чанков предложило»; (ii) фолд орфографии §G5; (iii) алиас-маршрутизация — этот третий канал ЗАКРЫТ правкой по ревью, см. §4-0(ж). ENRICHED-версия (memory.go:348) — вход снапшота edit-волны, значит он сдвигается. - Цена названа. Сдвиг НЕ тихий (
stagerun.goтребует явный--resnapshot) и классифицируетсяmoveBankOnly⇒repin.goотдаёт $0-репин каждой единице, в инъекцию которой терм не попадает. Платятся только единицы, где терм реально встречается. Для частотного терма (фамилия протагониста) это может быть почти вся книга — это решение владельца, а не гигиена, и оно вынесено вопросом в §7.
Что проверено ИСПОЛНЕНИЕМ и держится:
git statusпоbackend/internal/lang/data/— пусто: ни один файл ВОЛНОВОЙ плоскости не тронут, значитlang.EmbeddedVersion()байт-стабилен. ⚠ Это ВХОД волновой плоскости, а не содержимое банка — именно эту разницу первая редакция §2 и смешала.TestGoldenDeterminism— PASS без пере-захватаtestdata/golden/capture.golden. Голден пинит snapshot id обеих волн иrequest_hashкаждого вызова; если бы снапшот сдвинулся, он бы упал первым.TestTerminologyIsNotSnapshotFolded— PASS.- Новый пин
TestBankPlaneIsOutsideTheWaveFold(internal/lang/bankdata_test.go) держит это ВПЕРЁД: файл семей не должен попадать в набор, который хешируетEmbeddedVersion.
Что двигается. Состав батчей терминолога → RequestHash бэнк-батчей: G1 (состав юнитов), G3 (промпт-файл в system-сообщении) и G5 (фолд-счёт и Via меняют строку drafts: на проводе) двигают их ОДНИМ разом. Перекупка — центовая (весь проход терминолога на 10-главном стенде — $0.0057, D39.90). Вне снапшота и вне провода: G2 целиком, печать стоп-таблицы, дифф авто-банка, список эвиктнутых.
⚠ Расхождение с промтом, разрешённое в пользу §3 промта. Промт §2 G1 предлагал положить параметры семей в internal/lang/data/script-series.txt «новой колонкой или соседний файл». Проверено по коду: internal/lang/data/* целиком хешируется в lang.EmbeddedVersion() (embedded.go:72-82), а EmbeddedVersion фолдится в снапшот ВОЛНЫ безусловно (snapshot.go:381-389,442). Любая правка там сдвинула бы снапшот обеих волн, и classifySnapshotMove (repin.go:61-91) классифицировал бы это как moveOther — то есть без права на $0-репин: перекупалась бы вся драфт-волна книги, а не центовые бэнк-батчи. Это прямо противоречит §3 промта («волны/снапшоты книг НЕ двигаются») и ратифицированной позиции «терминология не фолдится» (config.TerminologyGate, TestTerminologyIsNotSnapshotFolded). Выбрана «соседний файл» в буквальном смысле — отдельная embed-плоскость internal/lang/bankdata/ со своим //go:embed и своей версией BankDataVersion(), которая логируется с прогоном (terminologist.go, поле bank_data=) и фолдится там, где ей место — в содержимом батча, то есть в RequestHash бэнк-батчей. Байты по-прежнему ЕСТЬ версия; они просто не выдают счёт за волну, которую не могут изменить.
Наблюдение по батч-чекпойнтам (строка 38, только наблюдение, работа в пак не входит). Бэнк-батч адресуется ординалом (chunk.Chunk{Chapter: 0, ChunkIdx: i}, terminologist.go), а порядок батчей — частотный (Batch → sort.SliceStable по batchFreq). G1 меняет СОСТАВ юнитов, значит меняет и суммарную частоту батчей, значит двигает те же ординалы: на первом прогоне после пака перекупаются все бэнк-батчи, а не только те, чей текст изменился. Цена та же центовая, но механика именно такая — «со слов» строки 38 подтверждается кодом.
Голден-счётчики волн прошли БЕЗ пере-захвата (см. п. 2 выше). Пере-захвата голдена в паке НЕ было.
§3. Самопроверка (мандат 12.07)
make battery— ЗЕЛЁНАЯ ЦЕЛИКОМ (build · vet · fmt · lint · test), локально, $0. ⚠ Первая редакция отчёта заявляла «батарея зелёная», прогнав только build/vet/test: гейтlintне гонялся и был КРАСНЫЙ — 3× errcheck в новомbankfixpack_test.go(runToSignatureStopвозвращает sentinel-ошибку*WaveSignatureStop, и её отбрасывание errcheck ловит). Поймано приёмкой; клейм был ложным, теперь предъявляется тем, что названо.-raceна всех затронутых пакетах (internal/pipeline83 с,terminology,miner,cmd/...) — EXIT 0.- Дифф
^func Test— ИСПОЛНЕНИЕМ (git grep HEADпротив рабочего дерева, не по памяти): было 685, стало 717, добавлено 33, удалён 1. УдалёнTestParseBanknoteTruncationTolerated— вместе с недостижимой веткой, которую он пинил (см. §1 «Опции»); его заменилTestParseBanknoteShortLastLineIsAParseFail. Новые:TestAutoBankRewriteNamesDroppedTerms·TestBankPlaneIsOutsideTheWaveFold·TestBankStopTableCarriesTheArbitrationRecord·TestBanknoteTruncatedIsReachable·TestConsolidationConflictsCatchesTheRunContradictingItself·TestContainmentPairSharesAUnit·TestDetectFamiliesGroupsBySharedRootAsymmetrically·TestEvictedBankRowsAreNamed·TestFamiliesOnBankFullFixtureAreBoundedAndWhole·TestFamilyChannelOffIsTheSeriesMap·TestFamilyDoesNotRegressAnEqualLengthSeries·TestFamilyKeepsAVariableLengthRankLineWhole·TestFamilyMergeRefusesAnOversizeUnit·TestFamilyMorphologyForZhIsLive·TestFamilyMorphologyIsData·TestFamilyMorphologyRefusesCorruptRows·TestFoldVariantsCountsConventionsAndShowsRawForms·TestFoldVariantsKeepsViaProvenanceHonest·TestParseBanknoteRejoinsASplitRendering·TestParseReplyAcceptsAMangledDeclineSentinel·TestParseReplyTakesTheConfidenceFieldBeforeRejoining·TestSelfContradictionIsReportedAtTheStop·TestSignatureMapJoinsAliasProposals·TestSeriesHoldsOnlyItsOwnMembers·TestFamilyMergesAcrossASeriesWhenTheRootIsShared·TestBankStopRowCarriesTheWinningVariantsSignals·TestTerminologistBudgetCutIsNotReportedAsAnEmptyReply·TestParseBanknoteShortLastLineIsAParseFail. Изменён на месте один:TestTerminologistEmptyReplyIsLoud(стал двухподслучайным — проза + настоящий пустой completion). - Изменены сигнатуры (обновлены все вызовы, включая тесты):
terminology.Merge(+foldDst),terminology.ParseReply(+conf map),Batch(seriesID→unitID),pipeline.writeAutoBank(+ctx),bankStopRows(+terminologyResult). - Фикстура
projectOptsполучила полеglossaryTokenBudget(0 → историческое 800, все прежние проекты байт-идентичны) — иначе ветка эвикции недостижима из теста. - archguard-тесты не трогал;
backend/.envне читал; PUML не рендерил (правкаbackend/docs/pipeline.puml— текстовая, синтаксис-ловушки из памяти учтены:;внутри метки нет, строк, начинающихся со спец-терминатора, нет). - МНОГОАГЕНТНОЕ АДВЕРСАРИАЛЬНОЕ РЕВЬЮ — ИСПОЛНЕНО по санкции владельца: 13 агентов-опусов (шесть независимых линз → опровергатель на каждую → синтез), $0, ~46 минут. Результат — §4-0-БИС: четыре major, включая ИЗМЕРЕННЫЙ регресс на замороженном эталоне и вред, ехавший на провод. Все закрыты; одиннадцать мутаций пере-проверены исполнением и убиты (родство-подстрока · инвертированный ранг семей · игнор разделителя · алиас-dst · несчитаемая битая уверенность · статистика по попытке · ordinal-порядок · плюс четыре из первого прохода). ⚠ Счётчик воркфлоу «36 выжило / 0 опровергнуто» — артефакт моего скрипта (id находок не сматчились с вердиктами опровергателей); реальное опровержение выполнено, его результаты — в тексте синтеза, и часть находок им снята.
- АДВЕРСАРИАЛЬНОЕ ревью №1 (author≠reviewer, одиночное) — ИСПОЛНЕНО отдельным агентом по санкции владельца: дифф + окружающий код + ТЗ + замеры-основания, с мутационным тестированием. Нашёл 1 major (см. §4а), 1 дыру-майнор и 4 выжившие мутации; опроверг три клейма этого отчёта. Все находки закрыты в коде и тестах, четыре мутации пере-проверены исполнением и теперь УБИТЫ (
M1гард серия-vs-семья ·M2игнорattempted·M3сигналы не заполняются ·M4инертный путь отдаёт копию). Батарея под-raceна затронутых пакетах — зелёная. - Ревью исполнением своего кода (соло, до адверсариального). Что пере-проверял отдельно и чем: детерминизм
MergeUnits(никакого выхода из итерации по map — id раздаются по отсортированным корням) · инертный путь (TestFamilyChannelOffIsTheSeriesMapтребует ТОТ ЖЕ объект-словарь) ·Spread()для кандидатов, собранных внеMerge(Forms=0→ считается как 1, обратная совместимость) · «уверенность» не ломает двухпольный ответ (TestParseReplyTakesTheConfidenceFieldBeforeRejoining, подслучайplain) · ложная тревога пустого батча при срезе бюджетом (отсеченоattempted) · кап семей — подобран НЕ на глаз, а прогоном по реальному корпусу при cap ∈ {8,12,16,24,32,∞}: 16 разрезает клан古月(6 отказов), 24 не отказывает ничему, дальше 24 ничего не меняет.
§4. Девиации от промта и почему
0-ТРИ (фикс-лист приёмки, всё мелкое — но одно структурное).
- БЛОКЕР:
make batteryбыла красной — см. §3; клейм отчёта исправлен. - MAJOR: WARN строки 130 был структурно МЁРТВ в проде.
ownerHandledполучал СЫРОЙ seed из стора, а тот со ВТОРОГО прогона авто-режима содержит собственные mined/auto-строки движка (seedGlossaryзасеивает авто-банк на старте,seeding.go:83-93) ⇒ каждый выпавший терм читался как «владелец решил», дифф всегда пуст, предупреждение не могло сработать НИКОГДА. Это risk 2 (self-exclusion), который сам файл документирует и обходитunsignedEngineSurfacesв двух других местах — и не обходил здесь. Мой тест это МАСКИРОВАЛ: кормил рукодельную map мимо стора. Стало:ownerHandled(unsignedEngineSurfaces(seed), rejects)+ тест ДВУМЯ реальными прогонами (терм уходит из дельты между ними, строки движка в сторе есть) — посадка «сырой seed» теперь убивается. - Две дыры пинов, обе на SPACE-RUN-форме: conf-тесты и тесты 129 кормили только ТАБ-строки, где
join(fields[1:]) == fields[1], поэтому и снятие уверенности на пробельном пути, и ре-джойн банкноты можно было отключить незаметно. Добраны пробельные формы; обе посадки убиты. bankParseVersionничем не потреблялся — не логировался и не фолдился, комментарий «logged with the run» лгал, артефакты v2.1 и v2.2 были неотличимы, то есть бамп подавался как механизм против дрейфа, а механизма не было. Стало: печатается на стопе (bank-mining: draft-side proposals folded, вместе соslice_version), комментарий честен.- Три ТИХИХ отказа канала семей — класс, который пак сам объявил нетерпимым: опечатка в script-колонке гасила канал молча (валидации не было, и флагманский тест общности объявлял
devanagari, который резолвер молча дропал — тест не доказывал ничего);family_affixбезfamily_min_members= канал молча выключен; словарь типов рассинхронен —nicknameлегитимен в банкнот-канале и доезжает доDetectFamilies, ноloadFamilyParamsего отвергал, а текст ошибки врал про состав словаря. Стало: скрипт валидируется по реестру диапазонов, пол-таблица отвергается, введёнterminology.CandidateTypes(шире классификаторскогоTypesровно наnickname, с объяснением почему), сообщение об ошибке перечисляет реальный набор, и пара получила правило дляnickname.
0-БИС (правки по МНОГОАГЕНТНОМУ ревью, шесть линз + опровергатели + синтез, всё опусами; 13 агентов, $0). Ревью нашло то, что соло-проход и первый адверсариальный пропустили:
- (ж) MAJOR: парсер банкноты дал РЕГРЕСС на замороженном эталоне. Реплей 56 реальных блоков coldrun-a: −6 строк против HEAD, +0, при
banknote_parse_failНЕИЗМЕННОМ во всех шести — то есть тихо. Механизм воспроизведён мной лично: трактовка «последнее поле не из словаря ⇒ часть перевода» портит строку, чей третий столбец — тип ВНЕ словаря (clan,event,proverb,onomatopoeia— 1.25% эталона):古月|Гу Юэ|clan→ dst «Гу Юэ clan»; а на ОБРАТНОМ порядке src становится ненаходимым и строка выбрасывается совсем. Исправлено принципом «разделитель несёт информацию»: строка с ТАБОМ или ПАЙПОМ прочитана позиционно (семантика HEAD), эвристика словаря применяется только к строке, разбитой прогоном пробелов — там, где неоднозначность и возникает. Дефект «Фан␣␣Юань», ради которого делался хвост 129, при этом чинится ЛУЧШЕ: в позиционном чтении он схлопывается внутри колонки.bankParseVersionподнят до v2.2 — правило парса изменилось, а тег версии в первой редакции остался прежним, что и есть тот дрейф, ради которого версия разделена надвое. - (з) MAJOR: перевод АЛИАСА становился dst терма и ехал на провод.
props[0]после моей правки мог быть предложением, пришедшим через алиас кластера — и попадал вst.Dst, то есть в строку банка, которую рендерит инъекция (memory.go:699-724), причём на $0-пути, БЕЗ модели и при ВЫКЛЮЧЕННОМ гейте терминолога. Ровно тот вред, ради предотвращения которогоViaи заводился, — через правку, котораяViaи вводила. Исправлено:st.Dstберётся только из предложения, сделанного НА СВОЕЙ поверхности; алиасные перечисляются в note со своим Via. - (и) MAJOR: третье поле, не являющееся голым числом, молча приклеивалось к переводу.
师父⇥наставник⇥95%давал канон «наставник 95%» приbad_lines=0— форма проходитwellFormedLemma, проходит экран языка, не эхо. Класс НОВЫЙ: промпт v3 сам просит третье поле. Исправлено тем же принципом разделителя: в таб/пайп-строке третья колонка ЕСТЬ колонка уверенности, нечитаемое значение считается (ReplyStats.BadConfidence) и НИКОГДА не склеивается. - (к) MAJOR:
MergeStats.Heldсчитался по попытке, а не по итогу. Из трёх «придержаний» на корпусе одно было ложным (蛊师и一转蛊师в итоге оказывались в ОДНОМ юните), и отчёт трижды называл ценой гарда именно несуществующий случай. Считается по ФИНАЛЬНОМУ разбиению: реально разрезаны巅峰и蛊虫, придержаний 2. - (л) MAJOR: две мутации в ядре пака выживали — родство подстрокой вместо морфемы и инвертированный ранг семей (обе меняют СОСТАВ вызовов, то есть деньги, при зелёной батарее). Закрыты пином точных чисел И ФОРМЫ разбиения плюс кейсом «серия
等资质и семья{丙等,丙等资,丙等资质}обязаны слиться через общую руну等». - (м) MINOR: WARN строки 130 срабатывал на ШТАТНЫЙ цикл подписи. Промоут в
mined_deltaили отклонение вmined_rejectsубирает терм из дельты НАМЕРЕННО, а дифф печатал его как молчаливую потерю и советовал сделать то, что владелец только что сделал. Исправлено: обе владельческие двери исключены из диффа. - (н) MINOR: единственная РАЗРЕШЁННАЯ D39.102 форма уверенности не была реализована. Число печаталось и не использовалось, хотя промпт и два комментария обещали ordinal-очередь ревью. Реализовано ровно там, где ему место: капнутый stdout-обзор (surface «что читать») сортируется «сначала неуверенное», полная стоп-таблица остаётся в ключевом порядке (reference-документ).
- (о) Лгущие комментарии сняты:
mining.goбольше не утверждает «с выключенным гейтом дельта байт-идентична» (это перестало быть правдой из-за (ж)/(з)); док поляbanknote_truncatedбольше не описывает удалённую tolerance-ветку и честно назван полом (обрыв, срезавший разделитель, он не видит); комментарий про蛊 среди 蛊-*больше не выдаёт непокрытый класс за работающий; ссылка на удалённуюproposalsFromObservedпоправлена.
0 (правки по первому, соло-адверсариальному ревью).
- (а) MAJOR: гард «серия сильнее семьи» растворял семью целиком. Было: если хоть один таргет нёс чужой серийный корень — слияние отменялось ВСЁ, включая не-серийных членов; клан
古月из пяти имён, три из которых образуют雄-серию, рассыпался на синглтоны — ровно та химера §B4, которую канал и строится закрыть, и приходила она через гард, который должен был её предотвращать. Блок при этом не считался ничем. Стало: придерживается только конфликтующий таргет, остаток семьи сливается, факт считаетсяMergeStats.Heldи попадает в WARN. ПинTestSeriesHoldsOnlyItsOwnMembers(мутация «убрать гард» теперь убивается). - (б) Тест родства был подстрочным и переусердствовал. Замер на реальном корпусе: 5 семей придержаны ЛОЖНО — серия
等资质против семьи{丙等, 丙等资, 丙等资质}: ни одна строка не содержит другую, хотя они очевидно делят морфему等, чья согласованность и есть предмет. Стало: «делят руну» = делят морфему (плотное письмо); придержаний на корпусе 11 → 3, и все три по делу. - (в) Дубли групп задваивали счётчик. Аффиксный и containment-каналы законно описывают один и тот же набор с двух сторон; дедуп ПОСЛЕ ранжирования (выживает самое специфичное описание) — придержаний 6 → 3, число в WARN стало означать то, что написано.
- (г)
Conf=0был неотличим от «уверенности нет». Обе печати прятали строку с уверенностью 0 — ровно ту, ради которой ordinal-ревью и существует. Стало: отсутствие = −1, ноль печатается. - (д) Мёртвый параметр
truncatedGenerationснесён вместе с недостижимой веткой и стейл-комментом (вторая половина опции промта; первую — проведение флага через finish — сделал сразу). - (е) Три дыры в тестах (мутации выживали): гард серия-vs-семья ·
attempted· заполнениеSignals. Закрыты пинами, мутации пере-проверены исполнением.
- Уверенность снимается по ПОЛЮ, а не регуляркой
\d{1,3}по хвосту строки. Промт просил «числовой хвост\d{1,3}снять КАК conf ДО ре-джойна». Буквальная форма съедает легитимный перевод, кончающийся числом («Пик 108»), у пары, чей промпт просит два поля. Реализовано: если полей ≥3 И последнее поле целиком 1–3 цифры в 0…100 — это уверенность. «Пик 108» — одно поле (один пробел, сплиттер режет по ≥2 пробелам), так что не задевается вовсе; проверено тестом в обе стороны. Число вне 0…100 остаётся частью перевода. DetectFamiliesвозвращает[]Family, а неmap[string]int. Слияние обязано знать ЯКОРЬ семьи, чтобы исполнить правило «серия сильнее семьи ТОЛЬКО при несовпадающих корнях»; из голых id якорь не восстановить. Итоговыйmap[string]intотдаётMergeUnits— то есть контракт «на входBatchидёт тот же словарь» соблюдён.- «Серия сильнее семьи» реализована как ПРИДЕРЖАНИЕ серийного таргета, а не как исключение серийных членов из семей и не как отмена слияния. Черновик §G предлагал «серийные члены из семей исключаются»; промт это уже амендировал 转-случаем. Исключение членов не выполняет критерий (а): при нём
十一转навсегда остаётся снаружи. Реализовано: юниты сливаются, если якорь семьи и корень серии делят морфему (sharesMorpheme); если нет — серия сохраняет СВОИХ членов, а семья формируется без них, и факт считается. Цена придержания, названная честно (пере-мерена по ИТОГУ, а не по попытке): на корпусе это 2 случая вида «реалия-семья, модифицированная рангом» —巅峰и蛊虫оказываются в другом вызове, чем一转巅峰/一转蛊虫. Альтернатива — разрешить слияние — даёт ранговый юнит-свалку; выбран гард + счётчик + WARN, чтобы решение было видно на холодном прогоне, а не выведено из банка, который сам себе противоречит. - Имена эвиктнутых — в ЛОГ, а не «рядом с
NEvicted» в строкеretrieval_state. Промт требовал форму БЕЗ новой миграции схемы; свободной TEXT-колонки в таблице нет (все шесть*_detailзаняты), а класть список эвиктнутых в чужую колонку (trust_gate_detail) — нечестно. Лог — вторая наблюдаемая плоскость движка, и именно её читают при бюджетных событиях. Вопрос владельцу/оркестратору: если список нужен durable — это колонкаevicted_detailи миграция; заводить её без слова не стал. - Перф
AttachKWICчерез готовый Aho-Corasick — НЕ делал. Автомат живёт вmembankнеэкспортированным (memory.go:882-927). «Чисто» это не ложится: либоterminologyначинает зависеть отmembank(инверсия слоя — пакет объявлен PURE, «no I/O, no network», и банк-стор в него импортировать нельзя), либо автомат выносится в новый общий пакет, что уже рефакторинг за пределами скоупа пака. Промт разрешал опцию «только если чисто ложится» — не ложится. - Ранжирование семей инвертировано против буквы ТЗ. §2 G1 требует «специфичный длинный корень бьёт короткий, ЗАТЕМ большая семья»; реализовано наоборот — сначала размер, потом длина якоря. Причина: при спековом порядке containment-якорь
一转(2 руны) обходит корень转(1 руна) и рвёт ранговую линейку на пары, то есть буквальный порядок ЛОМАЕТ критерий §2(а) того же ТЗ. На корпусе порядок кода строго лучше, и он запинен формой разбиения. Девиация не была объявлена в первой редакции §4 — поймано приёмкой, ратифицировано. - Снятие уверенности не гейтится данными пары — канал работает для любой пары, чей промпт-файл попросит третье поле. Риск-остаток назван: у пары с ДВУХпольным промптом легитимный перевод, чьё последнее слово — голое число ≤100, отделённое ДВОЙНЫМ пробелом («Пик␣␣99»), потеряет это число в уверенность. Уже, чем буквальная форма промта, но не ноль; если понадобится — это дата-декларация пары, отдельным касанием.
~/books/gu-zhenren/coldrun-a/не читал (см. хвост 129 выше): цена фолда 129 названа как «неизвестна», а не выдумана.
§5. Чего НЕ сделал и почему
- G4 (кластерный роутинг) — по промту в пак не входит (правило дизайна замера строки 5, кода не требует).
- Накопительный мердж авто-банка и освобождение слотов
emitRankCap— СТОП-решение владельца; сделан ровно $0-минимум (дифф + имена). - Строка 38 (ординальная адресация чекпойнтов) — только наблюдение, см. §2.
- Строка 140 (декларация банкнота-канала в shipping-c1) — вне пака; чинил только ПАРСЕР.
term-класс эмиссии, равноправный совет, кросс-модельные веса, self-consistency, селекция из вариантов, отказ-сигнал, эмбеддинг-фетч — закрыто числами D39.102, не строил.- ОДНОРУНОВАЯ голова семьи (
蛊,转,窍) — класс НЕ покрыт. Якорь обязан быть ≥2 рун, иначе одна общая морфема якорит полбанка; на дистилляции это значит, что转(кандидат банка) едет в другом вызове, чем 12 несущих его поверхностей. Включается ОДНОЙ строкой данных (family_containment_runes han 1), без правки Go. Не включил, потому что цена (размер юнитов) не замерена — предмет холодного прогона, не догадки. Строка бэклога — §7 п.4. - Семейные правила резолвятся по ЯЗЫКУ и применяются к поверхностям любой письменности.
FamilyMorphology("ja")/("ko")отдают han-правила и режут аффиксы по кане и хангылю. Замерен эффект на синтетике: 24 катаканных имени с общим «アリ» → один юнит → батч 8036 рун при бюджете 6000. Пары ja/ko в репо нет, та же скрипт-слепота уже в HEAD у серий — это норма-долг по ревью-вопросу общности, а не живой дефект. Строка бэклога — §7 п.5. banknote_truncated— ПОЛ, а не полный счёт. Обрыв, срезавший сам разделитель, флага не даёт (ранний возврат по пустому блоку выше проверки finish); по эталону это большинство length-обрывов. Буквальный фикс («ставить флаг и при пустом блоке») сделал бы ХУЖЕ — зажёг бы колонку на каждом обрыве переводчика в прогонах вообще без банкноты; нужен гейт поGates.Banknote.Enabled, и это отдельное касание. Строка бэклога — §7 п.6.
§6. План верификации эффекта на следующем ХОЛОДНОМ прогоне (D39.103 п.1)
Конкретно, что смотреть и где. Всё $0 — читается из артефактов прогона, отдельных вызовов не требует.
- Семьи вообще заработали. В логе строка
terminology finished— поляfamilies=,families_refused=,families_held=. Ожидание:familiesзаметно >0 (⚠ поле печатает число ДЕТЕКТИРОВАННЫХ ГРУПП, а не юнитов: на дистилляции 37 групп → 14 юнитов),families_refused=0,families_heldмалое (на дистилляции — 2). Еслиfamilies=0— канал инертен, и первое, что проверять, этоbank_data=в строкеterminology render: estimate before any call(плоскость данных доехала) иsource_langкниги. - Химера семьи на границе батча ЗАКРЫТА — прямая проверка. В стоп-таблице (
<project>.db.bank-stop.txt) взять клан古月и линейку转: все члены каждого должны иметь СОГЛАСОВАННЫЙ dst (одна конвенция клана, одна голова ранга). До пакаds1-b0дал все шесть членов слитно,ds1-b2— все семь раздельно (research/24 §B4). Если расхождение осталось — смотретьfamilies_refused/families_heldи WARN «renders OVER the size budget»: значит юнит разъехался по батчам или по капу. - Юнит не разъехался по батч-бюджету. WARN
terminology: a batch renders OVER the size budget— считать, сколько раз. Ненулевое количество ожидаемо и легитимно (юнит держится целым по дизайну), но если их много, следующий шаг — поднятьgates.terminology.batch_runes(конфиг, не код), а не резать юниты. - G2 нашёл то, ради чего строился. Поле
self_conflicts=вterminology finishedи WARN «consolidations of THIS run contradict each other» с именами. Основание-ожидание: 18/149 на живом банке (§A4). Ноль на большой книге — подозрительно, надо перепроверятьlexemeSubsetна реальных формах, а не радоваться. - Уверенность доехала и не врёт. В стоп-таблице колонка
confidence=. Проверять ДВЕ вещи: (i) она вообще непустая — значит модель выдаёт третье поле и парсер его снял; (ii)bad_linesвterminology finishedНЕ вырос против прошлого прогона — если вырос, модель ломает формат из-за третьего поля, и это откат промпт-правки, а не повод её терпеть. Полезность (сортирует ли она ревью честно) меряется глазами владельца на первом же листе: строки с низкой уверенностью должны быть теми, которые он и правда правит. Invented— класс, который надо прочитать первым. В стоп-таблице пометкаINVENTED. Ожидание: доля небольшая; каждая такая строка — консолидация, которой не предлагал ни один черновик. Это легитимно (роль видит всю книгу), но это же и первое место, где ищется выдумка.ConventionsпротивSpread. Строки, гдеspreadзаметно большеconventions, — чистая орфографическая дробь, которую фолд теперь склеил; именно на них §C2-3 раньше делил доказательства. Если таких строк ноль — фолд не сработал (проверятьNormalizeTargetFormна паре).- Строка 130 видна. WARN
bank-mining: terms that were in the auto-bank are NOT in the one this run just wroteс именами. На первом прогоне его не будет (нечего диффить); он появится на ВТОРОМ и дальше. Если появился — это и есть материал для решения владельца по накопительному мерджу. - Эвикция названа. WARN
memory: the injection token budget DROPPED bank rowsс именами иrows=. Если он есть — банк не доезжает до модели, и это отдельный разговор проglossary_token_budget, а не про терминолога. - Деньги.
terminology render: estimate before any call(до вызовов) противcost_usd/classify_cost_usdвterminology finished; ожидание — перекупка бэнк-батчей ОДИН раз, порядок центов, никакого касания волновых чекпойнтов (их $0-резюм должен пройти, что видно поtm_hit/resumeв отчёте прогона).
§7. Вопросы оркестратору и предложенные строки бэклога
РЕШЕНО оркестратором/владельцем при приёмке (войдёт в D-ноту лендинга):
- §7.1 — сдвиг edit-волны bank-only ПРИНЯТ. Слово владельца («не против реснапшота») совпало с рекомендацией сессии: новый dst лучше старого, сдвиг громкий, репин $0 там, где терма нет.
- §7.2 — миграцию под имена эвиктнутых НЕ заводим: лог достаточен; durable-форма уходит строкой бэклога с гейтом «доказанная потребность», вместе со строкой 49а.
- §7.3 — закрыто замером (0 прогонов ≥2 пробелов на 585 строк эталона).
- Девиация bankdata-плоскости РАТИФИЦИРОВАНА — отдельный embed вне волнового фолда вместо
script-series.txtпризнан правильным швом: иначе перекупалась бы вся драфт-волна. - Инверсия ранжирования семей ПРИНЯТА по корпусному пину; объявлена девиацией §4 п.6 (в первой редакции отсутствовала).
Историческая формулировка вопросов (для читателя D-ноты):
- Edit-волна двигается bank-only — принимается ли цена? Пак меняет поле dst дельты (ранг §C2-3 и фолд орфографии вместо сырого драфт-порядка), значит
memory_version, значит снапшот edit-волны. Сдвиг громкий (--resnapshot) и репинится за $0 для каждой единицы, где терма нет; платятся только единицы, где он встречается — для фамилии протагониста это почти вся книга. Альтернатива, если цена не принимается: держать dst дельты на предложениях СВОЕЙ поверхности в исходном драфт-порядке (тогда карта подписи снова разойдётся со стоп-таблицей — это и был дефект, который §G3 чинил). Моя рекомендация: принять, потому что новый dst лучше старого, а перекупка разовая и видимая. - Имена эвиктнутых durable? Сейчас — лог (миграции не заводил, см. §4 п.4). Столбец
retrieval_state.evicted_detail— это миграция, нужно слово. - Двойной пробел в
coldrun-a— искать ли (однаgrep-команда по замороженному эталону) и в чьей это сессии; я в артефакты не ходил. ⚠ Замер многоагентного ревью уже дал ответ по эталону: 0 прогонов ≥2 пробелов на 585 строк, то есть класс, ради которого делался хвост 129, на этой книге не встречается ни разу — фикс остаётся верным, но его цена по эталону нулевая, а не отрицательная только после правки §4-0(ж).
Предлагаю СТРОКАМИ БЭКЛОГА (таблицу ведёт оркестратор, я в неё не пишу):
- Одноруновая голова семьи —
蛊/转/窍в отдельном вызове от своей семьи; включается строкой данныхfamily_containment_runes han 1, гейт — замер размеров юнитов на холодном прогоне. Вес: скоро (то же касание, что и п. 7). - Скрипт-слепой резолв семей/серий — han-правила применяются к кане и хангылю; норма-долг общности, живого вреда нет (пары в репо нет), но при первой ja-книге это батч 8036 рун вместо двух в бюджете. Вес: когда-нибудь (к преп ja→ru, строка 81).
banknote_truncated— пол, а не счёт — обрыв, срезавший разделитель, невидим; фикс требует гейта поGates.Banknote.Enabled, иначе шум на каждом обрыве в прогонах без канала. Вес: когда-нибудь.- Пере-подтвердить
family_max_members = 24иfamilies_heldна первом холодном прогоне: 24 откалиброван на дистилляции в 150 поверхностей, у книги в 1000 глав список кандидатов другой (кап эмиссии 200 + реверс-секция). Еслиfamilies_heldвелик — гард ослабить до «родство по любому члену юнита» вместо «по корню серии». Вес: скоро (гейт — тот же прогон, что и §6). - Уверенность не гейтится данными пары — канал снимает третью колонку у любой пары, чей промпт её попросит; у пары с ДВУХпольным промптом остаётся узкий риск («Пик␣␣99»). Если понадобится — дата-декларация пары. Вес: когда-нибудь.