textmachine/docs/orchestrator-norms-scratchpad.md

71 KiB
Raw Blame History

Скратчпад оркестратора №23 — контроль исполнения лупа

Здесь НЕТ копий норм. Нормы живут в docs/ORCHESTRATOR_SESSION_PROMPT.md, копия факта стареет молча (D39.112). Здесь только (а) указатели-чек-лист, по которому я прохожу ПЕРЕД выдачей и ПЕРЕД лендингом, (б) стоячие правила владельца на этот луп, (в) живая раскладка слотов и журнал выдач. Файл рабочий и умирает вместе с очередью №23.

Стоячие правила владельца на этот луп (слово 11.09)

  1. Выполнить ВСЕ промты, задуманные в docs/NEAR_TERM_PLAN.md.
  2. Советоваться со старшим коллегой (Fable 5, постоянный контекст) — при выдаче промта, при ратификации, при лендинге и при ЛЮБОМ сомнении.
  3. Каждый выдаваемый промт писан по ролевой ноте; сверяться с ролевым промтом всегда.
  4. Сессия обязана эхом вернуть промт (блок 9 — своими словами, не пересказом).
  5. Приёмка и лендинг — строго по нормам ролевого промта.
  6. Сессия доводит свой пак до конца САМА и не беспокоит владельца до готовности; финальное исполнение контролирую я.
  7. Большинство паков идёт бэкенд-сессиям — следить за КАЧЕСТВОМ КОДА: никаких лишних велосипедов, воркэраундов и хаков ВОКРУГ проблемы. Нужно логически правильное работающее решение задачи, а не обход проблемы. Это отдельная ось приёмки, а не общее пожелание.
  8. Один промт на зону. Одновременно живут бэкенд · платформа · полигон · фронт; двух промтов одной зоны быть не может. Слот освобождается закрытием пака АКТОМ, а не сдачей работы.
  9. Пустые сессии владелец наспамил — роли назначаю сам, запускаю по одной и довожу до логического завершения.
  10. АВТОНОМИЯ (слово 11.09, 03:00): владелец отошёл и вернётся, когда весь ближайший план ИСПОЛНЕН. Вопросы решаю сам, совещаясь со старшим коллегой; владельца не жду.
  11. Мерило любого решения — в этом порядке: (а) главные ценности продукта — КАЧЕСТВЕННЫЙ КОНСИСТЕНТНЫЙ ИИ-перевод длинных книг/ранобэ; (б) архитектура и чистый код; (в) рефакторинг только действительно необходимый; (г) никакого велосипедостроения. Решение, выигрывающее у (б)(г), но не служащее (а), — неверное решение.

Перед выдачей промта — механическая сверка (перечтение автором рубежом НЕ считается)

  • 13 обязательных блоков — таблицей/грепом против §«Пишешь промт сессии?» (счёт равен нумерации).
  • Опровергатель-субагент к самому промту («найди отсутствующее и противоречащее»).
  • Блок 5 называет 24 уязвимых места ИМЕННО ЭТОГО пака — «сделай самопроверку» дефектна.
  • Разметка свободы у каждого пункта: «ровно так» либо «реши сам и аргументируй».
  • «Инструмент задан» — только после (а) что канон зовёт штатным, (б) не построено ли уже.
  • Фантом-гард: каждая D-ссылка грепается до НОМЕРА ПУНКТА, не до тела ноты.
  • Построчная сверка чужих путей/каналов против зонной таблицы CLAUDE.md.
  • Полигон-пак — дополнительный абзац норм замеров (арм без фактора · дедуп+декой · критик полноты на каждую фазу · пре-рег фриз ДО платных вызовов · активная проверка живости прогона).
  • Кодовый пак — свой абзац (вакуумный пин · клейм = команда · дифф ^func Test исполнением).
  • Пропорциональность: тяжесть аппарата соразмерна весу пака.

Перед лендингом

  • Контроль завершённости ДО приёмки, механически (блок 13).
  • Приёмка адверсариальная; дерево на время прохода заморожено ИЛИ верификатору выдан ГОТОВЫЙ путь.
  • Скипы печатаются рядом с числом ok.
  • Деньги — из сырого леджера двумя независимыми путями.
  • docs/scripts/counts.py --check и --lint перед ратификационным коммитом.
  • git diff -- <файл> по каждому файлу класса «пишет зона, коммитит оркестратор».
  • Коммит pathspec-формой; финал git status --short.
  • Акт закрывает носители ТЕМ ЖЕ движением (ряды бэклога, реестр дефектов, таблица активных промтов).

Раскладка слотов (живая)

Зона Промт Сессия Состояние
бэкенд BACKEND_BOUGHT_MEANS_DELIVERED_SESSION_PROMPT.md textmachine-b1 → свежая СЕССИЯ b1 ПОТЕРЯНА 15.09 при переезде окружения (textmachine-main-b1 — пустая сессия владельца, НЕ b1). Пак не завершён: круги не сошлись, нет «Чисел», таблицы мутаций, строки завершения. Сдача — в индексе main (sha git diff --cached --binary = 166997963c95…), бэкап ~/tm-b1-orphan-index.patch, копия только для чтения ~/tm-b1-orphan; гейт на копии зелёный (19 ok · 0 FAIL · lint 0 · 9 скипов · 23/23). Передача — разделом ред. 5 того же промта; опровергатель к нему сошёлся за три круга (21 → 3 мажора → 0 мажоров, шесть миноров последнего внесены); выдан 15.09 сессии textmachine-main-b1 словом владельца «выдай ему», confirm по слову 11.09 получен (эррата 15.09-а); эхо . ⏸ СДАН 15.09 ПО ПРАВИЛУ ОСТАНОВКИ П4 — круги не сошлись, остаток в таблице; со слов сессии: 29 путей, сырьё каталога вне репо в /home/ubuntu/tm-mut-logs-final-1509, числа мною не пере-сняты. Приёмка отложена словом владельца «Не отвлекайся пока от банка памяти, работай по нему»
платформа 🟢 СЛОТ СВОБОДЕН — пак принят актом D39.250, минор 0.15.0
полигон ЗАКАЗ СНЯТ ВЛАДЕЛЬЦЕМ 11.09 («полигон не надо выдавать»); промт готов и лежит, пере-выдача — только его словом
сквозной (вне кодовых зон) ЗАКРЫТ актом D39.252 11.09; промт в архиве с баннером. Стенд поднят до конца приёмки, гасить по pid
консилиум банка (вне кодовых зон) archive/prompts/BANK_MEMORY_CONSILIUM_SESSION_PROMPT.md textmachine-main-1e ЗАКРЫТ актом D39.253 16.09 с дофиксом и остатком; итог research/35, ряды 441450 заведены. Пять вопросов ждут владельца
фронт заморожен разморозка по критерию NEAR_TERM_PLAN.md

Резерв израсходован: textmachine-61 получила пак о падениях 11.09, как только слот освободился актом D39.249.

ПРИЁМОЧНЫЕ ЗАМЕРЫ ПЕРЕШЛИ КО МНЕ — не по вежливости, а по замеру. Бэкенд-сессию убило ЧЕТЫРЕ раза подряд на пере-снятии десяти записей (0 из 10 дважды, падало на первой). Причина найдена мною: это НЕ сторож и НЕ нехватка памяти — dmesg даёт 26 убийств, все constraint=CONSTRAINT_MEMCG, каждое в своём транзиентном юните tm.slice/tm-runs.slice/tm-test-*; сами слайсы memory.max = max. А мои прогоны идут в /init.scope с memory.max = max. ⇒ у неё потолок есть, у меня нет. Я гоню: десять пере-снятий (её имена, её команда дословно, мои копия и сборка) + по-пакетный battery-stand. Копия — ~/tm-11-accept/backend, построена по норме (test -f go.mod до и после, pwd сверен), tmmutate собран ОДИН раз, мутатор по копии ходит ОДИН. ⚠ В акте будет сказано, ЧЬИМ прибором снята каждая половина: полный гейт 169/169 · RED=167 · выживших 1 · UNKNOWN 1 — её, дошёл один раз до правок; десять пере-снятий и стенд — мои.

ДОЛГ ЛЕНДИНГА СНОВА ОТКРЫТ (акт D39.252): голова бампнута в ДВУХ носителях из трёх. Шапка 05-decisions-log.md и титул реестра стоят на D39.252; CURRENT-STATE — НЕТ: в docs/PROGRESS.md лежит секция бэкенд-сессии на 151 строку из 152, и коммит файла целиком унёс бы её под моим сообщением — ровно инцидент 54f8f6c, повторять нельзя. ⇒ бамп CURRENT-STATE едет ВМЕСТЕ с лендингом бэкенд-пака. До тех пор counts.py --check краснеет по голове — это ЗНАЕМОЕ расхождение, а не находка.

В очереди, написано и ждёт слота: BACKEND_FAILURE_YOU_CAN_SEE_SESSION_PROMPT.md, редакция 2 — выдаётся СВЕЖЕЙ бэкенд-сессии, как c9 закроется актом. Опровергатель нашёл 17 находок, и первая перевернула пак: я построил §1 на «движок лечит болезнь возбудителем», а замер говорит обратное — перевыпуск вернул текст 4 из 4, и в трёх случаях успешный ответ физически не влез бы в базовый потолок. Моя таблица лекарств отключила бы восстановление трёх чанков из четырёх и отменила бы D2 п.2 с пином TestRetryableSubset. Пере-снял сам — потолок 8496 делит популяцию успешных черновиков БЕЗ ИСКЛЮЧЕНИЙ (≤8496 прошли сразу ×3, >8496 упали и прошли на удвоенном ×3), а у редактора наоборот. ⇒ причин две, лекарство одно — вот это и есть пак. Ещё опровергатель снял: три моих контрольных числа не сходились (glob не дошёл до ~170 баз), D24.3 и D39.87 мис-атрибутированы, temperature у pro 0.4 а не 0.3, мест вызова два а не три, «пуста ровно err» — пусты пять колонок. Все исправлены.

Журнал выдач очереди №23

# зона предмет сессия эхо исход
1 бэкенд структура глав, ДИЗАЙН textmachine-50 своими словами, с возражением закрыт актом D39.245 (без сходимости)
2 платформа правда у двери textmachine-8e своими словами, с контрактным пингом закрыт актом D39.246 (с дофиксом)
3 полигон холодный прогон A (платный) textmachine-23 закрыт актом D39.247; строка 16 закрыта замером
4 ревью МОИХ записей (не пак зоны) textmachine-9a отчёт сдан; часть находок заландена 11.09
5 бэкенд консистентность, которую можно предъявить textmachine-c9 закрыт актом D39.249 с дофиксом (шесть посадок круга 1 выжили)
6 полигон ремонт прибора СНЯТ: зона вне скоупа словом владельца, промт в архиве
7 платформа ответ, не зависящий от везения (PD-448 · 162 · 466 · 139) textmachine-37 своими словами, 3 опасности + возражение закрыт актом D39.250, минор 0.15.0
8 бэкенд за одну единицу платим дважды textmachine-61 своими словами, 4 возражения — и первое ПЕРЕВЕРНУЛО посылку пака закрыт актом D39.251 с дофиксом
9 бэкенд купленное доставлено (ряд 291 + приложение 379) textmachine-b1 сессия ПОТЕРЯНА 15.09 при переезде окружения, пак не завершён → строка 11
10 сквозной ХОЛОДНЫЙ ПРОГОН B, платный, с вычиткой всего текста textmachine-82 своими словами, 5 опасностей — три исправили промт ПРИНЯТ актом D39.252, факт $0.396657
11 бэкенд ДОВОДКА пака 9 после потери сессии — раздел ПЕРЕДАЧИ ред. 5 того же промта textmachine-main-b1 своими словами, хеш индекса сверен, +5 недоделок сверх семи (две протухшие строки отчёта · цвет пинов снят не на HEAD · противоречие счёта читателей · §4.5(а) без исполнения · редрайв без катчера) — исходы отправлены выдан 15.09 после трёх кругов опровергателя (21 → 3 мажора → 0) и confirm владельца · ⏸ СДАН 15.09 по правилу остановки П4, приёмка отложена словом владельца «Не отвлекайся пока от банка памяти, работай по нему» · ПРИНЯТ актом D39.255 16.09 по слову «Да, начинай приёмку»: пять осей приёмки (батарея 23/23 · мой полный каталог мутаций 441/441 · её логи пере-разобраны моим прибором 437+4 · ось «отчёт↔код» 26 подтверждений, 0 мажоров · ось денег 79 чисел, все четыре пробы точны). Лендинг af88680, 29 путей, $0. ⚠ Мои ложные нули смены — в п.7 акта
12 — (вне кодовых зон) КОНСИЛИУМ «банк памяти длинной книги — как строить»: наследует банковую работу смены после отзыва проекта оркестратора; совет агентов, Fable 12 textmachine-main-1e своими словами; три опасности: шесть открытых решений против лимита в пять вопросов · исход «не термин» против закрытия D39.102 п.2 · угол «журнал с окнами» против почти пустых окон — все по делу, ответы отправлены ПРИНЯТ актом D39.253 16.09: сдан по правилу остановки, приёмка — пять осей вне консилиума (50 находок, 14 мажоров), затем круг дофикса и узкий закрывающий. Совет нашёл ратифицированный ответ на заглавный кейс владельца (D5 п.1, D7 правка 1), мимо которого прошли оба отозванных проекта. ⚠ Мои ошибки смены — в п.6 акта. Выдан 16.09 после механической сверки 13 блоков и ЧЕТЫРЁХ кругов опровергателя: 4 мажора + 15 миноров → 1 + 7 → 1 + 2 → 0 + 2, миноры последнего внесены. Опровергатель нашёл то, мимо чего прошли оба отозванных проекта: ратифицированный ответ на заглавный кейс владельца (D5 п.1, D7 правка 1) и что у движковых строк банка окон почти нет (since_ch > 0 у 2 строк на книгу, until_ch = 0 у всех). ⚠ Дважды мажор родила МОЯ правка: цитата о заморозке без её предмета · баннер выписки, объявивший опровергнутым верное утверждение
13 бэкенд БАНК ЗА $0 — фундамент «умного участка»: ряды 441 · 445 · 449 · 459 — (не выдан) промт написан 16.09, прошёл круг опровергателя фабла (7 мажоров: 5 внесены, M1 опровергнут моим замером — опровергатель напечатал «баз нет», а их 19, включая bank_stop_presented на 67 строк; 1 уточнён по ссылке). ПРИНЯТ актом D39.257 16.09: пять приборов (батарея 24/24 · мой прогон её 37 мутаций 37/37 без осечек · три оси вне сдачи · числа пере-сняты третьим прибором парсер-свободно · деньги 0 платных путей при контроле 192 файла). Два мажора названы, остаток принят. ⚠ Моя ошибка смены: снёс её рабочий корень мутаций — норма записана выше. ⚠ В самой выдаче явно попрошено ВЕРНУТЬ заказ, если сессия не свежая: норма «новый пак — новой сессии» стоит на том, что карта чтения писана для свежего читателя, а занятость чужого контекста снаружи не видна

| 14 | бэкенд | РЕШЁННОЕ НЕ ПЕРЕ-СПРАШИВАЕТСЯ: базис решённого как ИСТОЧНИК ОТВЕТОВ (ряд 130) + страж разрыва окон (ряд 490) | textmachine-main-57 | своими словами, десять пунктов, механика а не текст — и ДО начала работы названы два кандидата на отказ с замером (ряд 447 как смена продуктового поведения · сторож растущей книги, чья посылка вынесена владельцу и ответа не имеет). Ошибок понимания в эхо нет: воспроизведены порядок блоков, инвариант «базис — ИСТОЧНИК ответа, не фильтр», один писатель на двух границах, инвариантность отпечатка к способу отбора при пар-данной ширине, обязательность статуса draft и развилка юнитов. РЕЛЕЙ 17.09, через считанные минуты после выдачи: база прогона A в промте была названа НЕ ТА, и сессия уже строила прибор. Я вписал evidence/v16-readonly/project.db — замер: book_id guzhenren-coldrun-v16, глоссарий 53, Σcost_usd 0.43611; платный A — stand/books/bk_ROEHZBD46ALFI43E/project.db, глоссарий 69 (число всех банковых замеров), Σ 0.419423, сходится с ратифицированной суммой. Нашёл советчик, пере-снял я. Той же правкой доехали три ловушки материала: все book.yaml прогонов ссылаются на несуществующий /home/ubuntu-26/… (загрузка либо падает, либо ТИХО берёт конфиги головы) · вход контура mining-contrast.zh.txt в git отсутствует вовсе и живёт только в зеркалах прогонов · базы в WAL-режиме, копировать с -wal/-shm. ⚠ Урок мой: материал замера я назвал по имени каталога, а не по замеру содержимого — «evidence» и «readonly» звучали как платная улика, и этого хватило, чтобы не открыть базу. Заказ, отправляющий мерить не тот предмет, дороже битого якоря: якорь виден линтеру, неверная база — никому | ВЫДАН 17.09 после опроса кандидатов (свежих нашлось ДВЕ — 57 и 78; взята 57, второй сказано не занимать зону). Оба рубежа пройдены: механическая сверка 13 блоков (27 якорей, все живы, токен по адресу, коротких нет) и субагент-опровергатель — 12 находок, 9 денежных, все внесены. Чем окупился опровергатель: (1) я вписал «текста в коде УЖЕ НЕТ, 0 совпадений» о строке, которая ЖИВА ДОСЛОВНО, — грепал по одному файлу, увидел начало длинной строки, обрезанной по ширине, и прочёл обрезок как ФАКТ; у неё вдобавок третий носитель, голден операторских сообщений, которого я не видел вовсе; (2) замер M1 был заказан на копиях купленных баз, а таблицы чанков в них НЕТ (17 и 16 таблиц) — предмет из них не строится, нужен исходник отдельным файлом; (3) порядок записи на границе стопа задаёт САМ КОД («последним пишется то, чья потеря дешевле»), и по нему базис идёт ПЕРЕД памятью флажка, а не пятым, как велел консилиум; (4) ширину отпечатка я заказал константой Go — это утечка пары в общий слой, закрытая D39.50, причём на денежном предикате. И урок абзацем ниже — про эту самую выдачу: приоритет пака у владельца я НЕ подтверждал. Слот бэкенда свободен, но «слот свободен ≠ работу зоны надо заказывать»; поэтому промт лежит файлом, исполнитель не назначен, и решение о выдаче — за владельцем. ⚠ В самой выдаче, когда она состоится, повторить норму строки 13: ВЕРНУТЬ заказ, если сессия не свежая |

ПОЛИГОН СНЯТ ВЛАДЕЛЬЦЕМ 11.09. Я предлагал пак трижды — ed, 5c (обе отработавшие, отказались ПО НОРМЕ и были правы) и свежей 37, — после чего владелец сказал «полигон не надо выдавать». Выдача 37 ОТОЗВАНА тем же часом. ⚠ Урок не про полигон: я трижды искал адресата для заказа, приоритет которого не подтверждал у владельца. Слот зоны свободен ≠ работу зоны надо заказывать.

Что я должен помнить, пока паки идут

  • Ключи прогона A: путь выдан (backend/.env), файл НЕ читать; живость ключей проверяется ПЕРВЫМ платным вызовом. Отказ по авторизации — стоп сессии и мой поход к владельцу.
  • Пре-рег-таблица прогона A приходит мне ДО фриза — читаю её прежде, чем потратится первый цент.
  • Релей НЕ СОСТОЯЛСЯ, и сказала это не я. Улика прогона A про многоединичную главу должна была уйти движковой сессии ОТ МЕНЯ отдельным сообщением с её эхо-подтверждением — не ушла, и дизайн-пак записал это у себя: backend/docs/CHAPTER_STRUCTURE_DESIGN.md:1869=о многоединичной главе. Улика найдена и положена в трекер — ряд 409, — чтобы не умереть вместе с этой запиской. В чужую зону я не пишу: §13.2 п.6 того документа снимается ПИНГОМ движковой сессии, а не моей правкой.
  • Кросс-зонная цена перекроя (unit_resolutions платформы, экспортные id термов) придёт от движковой сессии пунктом отчёта — отнести её платформе должен я.

К приёмке прогона A — проверить лично

  • Фриз-коммит и девиация разошлись, и это ЗАКОННО, но должно быть названо. Бинари собраны из клона на b0f5d89; драйвер eval/door_to_file/drive.sh правлен ПОСЛЕ фриза отдельным коммитом 44b33d9 («адрес локального провайдера значит противоположное в двух фазах: обязателен в дыме, запрещён при деньгах на проводе»). Норма пака: девиация — НОВЫМ коммитом и ЯВНО в отчёте. ⇒ при приёмке сверить, что отчёт её называет, и что расхождение «бинари b0f5d89 / драйвер 44b33d9» объявлено, а не замолчано.

Чему меня научили опровергатели 11.09 (не повторять)

  1. Санкция владельца, известная «со слов», носителем НЕ является. Оба пака ссылались на разрешение платного прогона как на факт, а в дереве его не было ни строкой. Завёл носитель — NEAR_TERM_PLAN.md §«Решения владельца».
  2. Пак не заглянул в СВОЮ зону записи. Дизайн-пак заказывал то, что уже лежит в backend/docs/ дизайном-оф-рекорд и рабочим прибором. Теперь у каждого пака первым делом — «что уже лежит у тебя».
  3. Трудность, которой нет. Я написал платформенной сессии, что валидация каталога обязана отличать первый прогон, — каталог создаётся на интейке ДО строки в БД, и различать нечего. Пин на недостижимую ветвь толкает сессию строить exemption, чтобы было что пинить.
  4. «Одно определение на две площадки» бывает недостижимо по построению — опросный путь замка не берёт, и контракт эту асимметрию ратифицировал. Мерило — число ОПРЕДЕЛЕНИЙ, а не площадок.
  5. МОЙ КОММИТ УНЁС ЧУЖУЮ СЕКЦИЮ — 54f8f6c, 11.09. Я правил ОДНУ строку головы в docs/PROGRESS.md и взял файл pathspec-формой целиком, не сделав git diff -- docs/PROGRESS.md; в тот же момент движковая сессия положила туда свою записку-план, и 32 вставки из 33 оказались её. История НЕ переписана (переписывание стёрло бы незакоммиченные правки параллельных сессий), содержимое цело, атрибуция восстановлена сообщением зоне. ⚠ Норма стояла в моём ролевом промте и не сработала, потому что я читал её как «про чужое в ИНДЕКСЕ». Ловится дёшево и постфактум: объём коммита против объёма своей правки — одна строка против тридцати трёх.
  6. «ЭТИ ДВА МЕХАНИЗМА НЕСОВМЕСТИМЫ» — УТВЕРЖДЕНИЕ О КОДЕ, И ЕГО НАДО СПРАШИВАТЬ У КОДА. Я написал в платный пак, что портированная заглушка и провайдер local несовместимы («разные адаптеры»), и запретил бы сессии единственный штатный $0-стенд. Поймала зона: заглушка лежит В РЕПО с комментарием «the P9 live-probe's $0 stand-in, ported», а рядом zeroCostPipeline выбирает модель по Kind == "local". ⚠ Класс ошибки тот же, что «заказал уже построенное», только вывернутый: я объявил НЕВОЗМОЖНЫМ то, что построено и запинено. ⇒ прежде чем писать «несовместимо/невозможно/нечем», грепни предмет — отрицательное утверждение о дереве стоит команды ровно так же, как положительное.
  7. Я ПОСТАВИЛ ПИН, УТВЕРЖДАЮЩИЙ МОЛЧАНИЕ, НА САМЫЙ ДОРОГОЙ ГЕЙТ ПЛАТНОГО ПАКА. «Драйвер отказывает при vcs.modified=true» на бинаре из линкованного воркри выполняется всегда: строк vcs.* там НЕТ вовсе. Поймала зона на первом же замере, я пере-проверил чтением готовых бинарей. Норма ушла в ролевой промт (фриз-дерево — КЛОН, третье условие отказа — отсутствие штампа). ⚠ Класс знал я сам: он записан в CLAUDE.md отдельной строкой про вакуумные пины — и всё равно воспроизвёл его там, где он стоит денег.
  8. Атрибуция нормы к ноте проверяется телом ноты. Ссылка на D39.108 п.1 в моём ролевом промте фантомна: норма верна, нота о другом. Эррата внесена.

Долг, замеченный попутно (не терять)

  • ЛЕНДИНГ ПАКА «КУПЛЕНО — ЗНАЧИТ ДОСТАВЛЕНО» (передача 15.09) обязан тем же движением: (1) расширить ряд 375 воспроизведённым сессией textmachine-main-b1 случаем — memberDrops (backend/internal/pipeline/status.go) считает члена с МЕТКОЙ СТОПА выпавшим, и формулировки Т3/Ч1 пака («навсегда» / «требует проверки человеком») лгут после редрайва отказанного члена и повторного отказа; верное лечение — третье состояние члена, решение 15.09 «остаток, не заплата»; (2) перенавести 17 якорей docs/, сдвинутых сдачей b1 (список — второй круг опровергателя передачи); (3) бамп головы в CURRENT-STATE; (4) ряды контракта 14 для трёх причин (retry_unaffordable · cancelled · attempt_timeout), ряд «расхождение витрин status/экспорт», ряд переименования echo_edit_units, анкор техдолга; (5) решения при приёмке: смысл эхо-метрики на эдит-волне и ранг 4 новой причины. Пак закрывается ПО ПРАВИЛУ ОСТАНОВКИ (круг 8 нашёл дефекты в комментариях починок круга 7 — решение 15.09 «стоп»). (6) Перенос слота гранта на метки стопа и cancelled (пробы B/C второго читателя: юнитов за слот 1 → 2, трата прогона $0.00182 → $0.00364) ОСТАВЛЕН решением оркестратора 15.09 по действующему правилу 03.09 (эррата 03.09-а к D39.170) — дописать в ряд 232; семантика переноса остаётся открытым вопросом владельца. Пробы D/F — числа стали честнее, решения не требуют.

  • ДОЛГ ОБЩНОСТИ, НЕ ЗАВЕДЁН НИ В ОДНОМ НОСИТЕЛЕ (замер 15.09): нормализация ИСХОДНИКА — таблица backend/internal/text/data/trad2simp.txt (встроена go:embed в ядро) и свёртка катаканы в хирагану — зашита в text.NormalizeSourceKey, у функции нет параметра языка, мест вызова вне тестов 55; в configs/langpacks/ данных нормализации исходника 0. ⇒ китайская и японская специфика живёт в Go-ядре и применяется ко ВСЕМ исходным языкам (японский текст получает китайскую свёртку кандзи). Поиск носителя — python по BACKLOG.md, 13-tech-debt-anchors.md, 12-go-style-notes.md, 09-target-architecture.md: по предмету 0, контроль | 330 | найден. Строку бэклога завести вместе с проектом банка (разбор Fable 15.09 — граница «ядро: тождество ключа / данные языка: таблица свёрток»).

  • Якоря розданы не все. Платформе — 3 (её пак §4.5), движку — 3 (backend/docs/DISCLOSURE_LAW_DESIGN.md, дизайн-пак §4.9). Полигонные 5 (docs/experiments/) НЕ вошли в пак прогона A сознательно: он платный и идёт по жёсткому порядку фаз, а док-гигиена потребовала бы релея посреди прогона. Отдать их с пере-выдачей «РЕМОНТА ПРИБОРА». Фронтовые 3 — зона заморожена, отдать первым касанием при разморозке.

  • Числа следующего бэкенд-пака пере-сняты МНОЮ, а не взяты из отчёта воркфлоу (11.09): Spread и в mining.go:383, и в bankexport.go:135 описан дословно как «how many DISTINCT renderings the DRAFTS produced» — счёта по ОТГРУЖЕННОМУ тексту нет (контроль: 144 файла в internal/pipeline); порог короткого ключа minKeyLenHan = 2 с пер-записным allow_short; точность глоссарного класса k6 = 0.0667 в books/gu-zhenren/labels/metrics.json (контроль: у соседних классов 1.0, 0.8333, 0.1667, 0.0 — прибор спрошен у существующего предмета и различает).

  • 11 уехавших якорей в ЧУЖИХ зонах (counts.py --lint, 11.09): полигон 5 (docs/experiments/) · бэкенд 3 (backend/docs/DISCLOSURE_LAW_DESIGN.md) · фронт 3 · платформа 3 — платформенные уже врезаны в её пак §4.5. Свои пять я починил (f9216cd). Остальные раздать ПАКАМИ их зон, не чинить самому.

  • Воркфлоу про банк памяти (wm0j2l4kz) умер, отдав пустой файл — вопрос владельца «что банку памяти нужно для качества перевода» носителя не получил; пере-задать при паке «выдача, которую видит читатель».

Класс ложного нуля, купленный 16.09: обёртка вокруг ВСТРОЕННОЙ команды даёт 127, а счётчик печатает «0»

Мой советчик-фабл отчитался «баз прогонов на хосте нет: project.db — 0 под /home/ubuntu». Баз девятнадцать. Механизм он назвал сам, и он воспроизводим: прибор был timeout 60 command find … | wc -l. timeout запускает ВНЕШНЮЮ программу, а command — встроенная оболочкиexit 127 («команда не найдена»), ноль строк на выходе, и wc -l честно печатает 0 — как будто это результат ПОИСКА.

И вот что делает класс опасным, а не просто глупым: контрольные величины рядом БЫЛИ. Он напечатал «books/ — 17 записей» и «*.db под репозиторием — 0». Обе верны и обе отвечают на ДРУГОЙ вопрос — про репозиторий, где баз и правда нет. ⇒ контроль обязан стоять у ТОГО прибора, который дал ноль, а не рядом с ним: контроль от соседнего прибора доказывает работоспособность соседа, и ничего больше.

⇒ Практика: у любой пайплайн-команды, чей ноль несёт вывод, печатать PIPESTATUS/код возврата ПЕРВОГО звена, а не только число строк. find_exit=127 виден сразу, «0» — не виден никогда.

УЛИКА ПЛАТНОГО ПРОГОНА ОТКРЫВАЕТСЯ ТОЛЬКО СВОИМ РИДЕРОМ — движковый стор её либо не пустит, либо ПЕРЕПИШЕТ (16.09)

Нашла бэкенд-сессия на банк-паке, проверено мной деревом. База купленного прогона отстаёт по схеме от головы (замерено: A-after на 16 при голове 18), и дальше развилка, у которой обе ветви плохи:

  • store.OpenReadOnly (backend/internal/store/store.go:161=current != len(migrations)) на несовпадении ОТКАЗЫВАЕТ SchemaMismatchError — прочитать улику им нельзя;
  • обычный store.Open идёт через миграцию (backend/internal/store/migrate.go:673=for v := current; v < len(migrations); v++) и МОЛЧА ПРИВОДИТ СХЕМУ К ГОЛОВЕ — то есть переписывает купленный прогон, и улика перестаёт быть уликой.

Норма: улики платных прогонов читаются собственным ридером на mode=ro&immutable=1, замеры снимаются на КОПИЯХ, хеши копий печатаются. ⚠ immutable=1 обязателен, а не желателен: обычный mode=ro создаёт рядом с базой файл -shm, то есть трогает каталог улики (поймано первым же зондом той же сессии).

⚠ И общий класс, ради которого это здесь: инструмент своей зоны, применённый к замороженному артефакту, чинит его под себя. Спрашивать надо не «пустит ли меня прибор», а «что он сделает с предметом, когда пустит».

РАБОЧИЙ КАТАЛОГ ЖИВОЙ СЕССИИ НЕ УПОМИНАЕТСЯ В РЕПОЗИТОРИИ ПО ПОСТРОЕНИЮ — греп его «мусором» и назовёт (16.09, моя ошибка)

Владелец сказал снести мусор. Я собрал кандидатов прибором «упоминается ли каталог в файлах репозитория, включая архив» — 5034 файла, у семи целей ноль упоминаний, — и снёс 268 МБ. Среди них был tm-mut-11, рабочий корень идущего мутационного прогона бэкенд-сессии (tmmutate -root ~/tm-mut-11/tree -battery). Окно сноса 19:3619:43 пришлось на её первый прогон; она остановила его «по своей причине» и перезапустила в 20:22, то есть ущерб мог остаться неопознанным с обеих сторон.

Класс: отрицательный замер был верен и отвечал не на тот вопрос. «Каталог не упомянут в репозитории» и «каталогом никто не пользуется» — РАЗНЫЕ утверждения, и для временного рабочего дерева первое верно ВСЕГДА: его для того и создают вне репозитория, чтобы он там не числился. Прибор ответил на свой вопрос.

Норма перед rm -rf любого каталога вне репозитория: к грепу по репозиторию ОБЯЗАТЕЛЬНО добавить ps -eo pid,cmd | grep <имя каталога> и lsof +D (или проверку mtime свежее часа) — и печатать их рядом с решением. Пусто в обоих — сносить; занято — не трогать и назвать владельцу, чей это процесс.

⚠ И вторая половина нормы, дороже первой: убил чужое — пиши той сессии САМ, с точным временным окном, не дожидаясь, пока она наткнётся. Её числа, снятые в окно вмешательства, недействительны целиком: прогон, у которого убрали корень, не отличает «мутация не поймана» от «файла нет».

ВОПРОС ВЛАДЕЛЬЦУ ЗАДАЁТСЯ ПОСЛЕ ГРЕПА, И В САМОМ ВОПРОСЕ НАЗЫВАЕТСЯ, ГДЕ ИСКАЛ (17.09, поймал владелец — ДВАЖДЫ за один разговор)

Замер. Из пяти продуктовых вопросов, поданных владельцу 17.09, на ДВА ответ лежал в репозитории:

  • «кто платит за доставленную пустоту» — ратифицировано словом 11.09 и записано в NEAR_TERM_PLAN.md, который я читал получасом раньше. ⚠ И тот же файл сорока строками ниже держал вопрос ОТКРЫТЫМ с тремя вариантами — то есть носитель противоречил себе, а я переписал из него вопрос, не заметив ответа выше;
  • «что делать с противоречием в банке» — алгоритмы спроектированы консилиумом, акт которого я сам же и писал (D39.253); открыт там ровно один пункт, и не тот, который я принёс. Ответ владельца в обоих случаях был «разве это не записано?» и «ты вообще их знаешь? они вроде как в ресёрче лежат».

ПЕРЕД тем как ставить владельцу вопрос: грепнуть предмет по журналу решений, плану, ресёрчам и зонным бэклогам. В тексте вопроса НАЗВАТЬ, где искал и чего не нашёл. Не можешь назвать место поиска — значит не искал, и вопрос не задаётся. ⚠ Родственный класс той же смены: владельцу был подан вопрос о ЗАТВЕРДЕВАНИИ нарезки, на который он ответил верно — и совпал со СВОИМ ЖЕ решением 09.08, лежащим в research/27 §3а; я вдобавок «поправил» его ответом про момент РАЗМЕТКИ, то есть возразил мимо предмета (снято D39.258 п.7).

СЛУЖЕБНАЯ РАМКА СОБСТВЕННОГО ФОРМАТА — НЕ ЧАСТЬ ДОКЛАДА ВЛАДЕЛЬЦУ (17.09, замечание владельца)

Внутренняя инструкция велит сперва перечислить себе, что нужно дальше. Это перечисление ушло в текст, адресованный владельцу, под заголовком «Приватно, что нужно» — и он спросил, что это значит и почему появилось недавно. ⇒ Рассуждения о собственном порядке работы остаются у себя; владельцу идёт доклад. Ярлык «приватно» на тексте, который показан человеку, вдобавок ложен. Формулировка канона рядом: с владельцем говорим по-человечески, без трекер-жаргона, ошибку называем прямо и не размазываем.

ЛИТЕРАЛ, ОПИСЫВАЮЩИЙ ЧУЖУЮ ЗОНУ, НЕ ЧИНИТСЯ ПО ЧУЖОМУ НЕЗАКОММИЧЕННОМУ ДЕРЕВУ (17.09, поймал блокирующий гейт в первый же час)

Замер. Платформенная сессия завела две строки в свой регистр дефектов и сообщила, что счётчики в шапке docs/PROGRESS.md разошлись. Я поправил их сразу — и записал в общий носитель величину, верную ровно пока её правки лежат рядом незакоммиченными. Гейт остановил коммит; разбор показал, что приборов ДВА и они отвечают на разные вопросы: --check читает рабочее ДЕРЕВО, --check --from-index — содержимое КОММИТА, и хук судит вторым. В дереве регистр нёс 468 строк и 107 открытых, в истории — 466 и 105.

⚠ И вторая половина, которая хуже первой: мои «поправленные» 110 не совпадали НИ С ОДНИМ из состояний — я пересчитал по числу из чужого письма («завела две строки»), а не замером. Арифметика по сообщению соседа — не замер, даже когда сосед прав.

Литерал в своём носителе описывает РЕПОЗИТОРИЙ, а не чьё-то дерево. Пока чужой пак не сдан, число держится на значении истории; оно поедет ТЕМ ЖЕ коммитом, которым принимается пак. Крутить его туда-сюда бессмысленно: литерал один, состояний два, и любое значение красит один из приборов.

⚠ Класс родствен «прибор ответил на свой вопрос»: здесь два прибора отвечают на РАЗНЫЕ вопросы, оба верно, и ошибка — не в них, а в том, какой из них считать судьёй. Судья — тот, которым судит гейт.

НАИВНЫЙ СКРИПТ ПРОТИВ ОБЩЕГО ПРИБОРА: дважды за смену я принял отказ СВОЕГО замера за дефект ГЕЙТА (17.09)

Случай первый — счётчики регистра. Гейт трижды остановил мой коммит на расхождении литерала. Я четыре раза подставлял значение (105 · 110 · 111 · 466/468), считая колонку статуса собственным кодом, — и каждый раз мимо, потому что индекс колонки брал не тот. Верное число прибор ПЕЧАТАЛ в каждой строке вывода: «против пере-счёта 108». Ответ лежал в выводе, а я вычислял его заново.

Случай второй — «щель» в линтере. Ревизор сообщил, что якорь без корневого каталога после выноса молча числится внешней ссылкой. Мой скан «подтвердил»: 108 таких якорей. Я собрался чинить гейт — и перед правкой прогнал ЕГО ЖЕ логику на живых примерах: короткий путь сперва достраивается ШЕСТНАДЦАТЬЮ префиксами, и лишь если не нашёлся ни под одним, судится первый сегмент. Все 101 «слепых» якоря прибор находит и проверяет. Не находятся шесть, из них четыре — ссылки в ЧУЖИЕ репозитории (законное молчание), два — короткие пути в зоне полигона (пинг зоне, не правка гейта). Дыры не было.

Прежде чем чинить общий прибор, воспроизведи его отказ ЕГО ЖЕ логикой на конкретном входе. Свой скан, написанный за минуту, не равен инструменту, который писался и чинился месяцами: у него есть префиксы, исключения, дедовщина и знаменатели, которых у наброска нет. ⚠ Родственная формулировка канона: «прибор ответил на свой вопрос» — здесь приборов ДВА, и мой отвечал на более простой вопрос, чем гейт.

⚠ И цена ошибки несимметрична: не найденный дефект стоит одной находки, а «починка» исправного гейта портит инструмент, которому верят все смены — тем более теперь, когда он БЛОКИРУЕТ (D39.260 п.3).

НОМЕР РЯДА — ЧИСЛО-ОМОНИМ: массовое закрытие строк трекера автоматическим поиском НЕВОЗМОЖНО в принципе (17.09)

Задача выглядела механической: в трекере 29 рядов несут маркер закрытия в теле и весят 47 КБ, а конвенция единого трекера велит закрытые ряды из таблицы удалять, оставляя номер решения. Я написал под это четыре прибора подряд, и все четыре дали неверный ответ.

  1. Фильтр «есть акт и нет слов о живом остатке» выдал 12 кандидатов — и среди них ряд 224, у которого я САМ в тот же день актом D39.262 записал, что закрыта только платформенная половина. Прибор не увидел остаток, потому что в клетке он назван номерами других рядов (479, 353), а не словом «остаток».
  2. Поиск подтверждения в журнале решений объявил девять из двенадцати неподтверждёнными — но грепал только ЖИВОЙ файл, тогда как тела закрытых эр (D39.64, D39.69, D39.164) лежат в архивных слайсах.
  3. Сбор образцов формулировок напечатал «фраз с закрытием и числом: 0» — рядом с прибором, который в том же выводе нашёл десяток таких фраз. Ноль был артефактом шаблона ([^.|] спотыкается о точку внутри D39.243), и опроверг себя сам.
  4. Поиск окном ±130 знаков по всем десяти носителям (1.63 МБ) отработал технически верно и доказал НЕ ТО: для ряда 141 он поймал «нормы D39.141 исполнены» — номер НОТЫ; для 359 — «тестов 261→359», количество тестов; для 409 — «обработка daily_ceiling/409», HTTP-код; для 115 — «принят D39.115». А ряд 324 попал в кандидаты потому, что слово «ЗАКРЫТ» относится там к ПРЕДМЕТУ — «вход рендера закрыт», — а не к статусу ряда.

Утверждение «ряд N закрыт» неотличимо прибором от «числа N» в другом смысле: номер ноты, номер теста, HTTP-код, количество, номер строки кода. Никакая regexp-точность это не лечит — омонимия в самих данных. ⇒ Порядок работы: только поштучно, партиями по три-пять рядов, читая КЛЕТКУ целиком и тело акта по ссылке. Автоматика допустима лишь как генератор КАНДИДАТОВ на чтение, и её список обязан идти с пометкой «не проверено».

⚠ Цена ошибки несимметрична и потому решает: не удалённый закрытый ряд стоит лишних килобайт, а удалённый живой стирает работу, которую никто не восстановит — в трекере ряд и есть носитель. Поэтому при сомнении ряд остаётся.

⚠ И отдельно: ряд 315 закрыт ЗАМЕРОМ, а не актом, а ряд 485 — половиной. Удаление такого ряда уносит сам замер, если он никуда не перенесён ⇒ прежде удаления факт переезжает в D-ноту или в справочник якорей техдолга.

Тот же класс через час, в чистом виде: 26 → 7 → 0 на одной задаче

Проверял, у всех ли живых ресёрчей стоит ⚠ superseded-баннер (норма docs/archive/README.md: частично устаревший research НЕ переносится, а получает баннер на месте). Один и тот же вопрос, три прибора подряд:

прибор «без баннера» что он на самом деле искал
^> *[⚠⛔✅] в первых 6 строках 26 из 42 цитату, начинающуюся СРАЗУ со значка
`^>.*(⚠
`(⟶ значки [Сс]татус:)` в первых 15

Истина — ноль: баннеры стоят у ВСЕХ сорока двух. Первый прибор завышал в двадцать шесть раз против нуля, и его выдача выглядела осмысленным списком работы на полдня.

Список «того, чего нет», обязан проверяться на ОДНОМ известном экземпляре, прежде чем стать планом. Я чуть не пометил research/22 как беспризорный — у него шапка оркестратора с лендинга 24.07 прямо во второй строке, и в тот же заход выяснилось, что «0 входящих» у него тоже ложь: по короткой форме ссылки на него указывают СЕМЬ файлов (контроль: на соседние обзоры 8 и 15). Два ложных нуля об одном файле в одном замере.

⚠ И отсюда практическое: маркеры в этом репозитории разноформатны по историческим причинам (, , , , «РЕВЬЮ-ШАПКА», «СТАТУС:», «Статус:»), потому что ставились разными сменами. Любой обход документации по одному значку даст ложный список; правильный шаблон перечисляет формы и печатает контроль «умеет ли он НЕ находить» — у меня он дал 0 файлов со статусом ниже порога, и только это сделало ноль доказанным.

⚠ Я ОБЪЯСНИЛ ЧУЖОЕ ПАДЕНИЕ НАГРУЗКОЙ, НЕ ИМЕЯ ЗАМЕРА — и это ровно то, за что я час назад хвалил зону (17.09)

Запустил третью ось приёмки с разрешением гонять пакеты, когда машина была свободна. Через двадцать минут зона вошла в пятичасовой пере-прогон, и два тяжёлых набора пошли рядом. Увидев это, я поставил оси паузу и написал зоне: «падение может быть конкуренцией за память, не ищи регрессию».

Довод был правдоподобен и НЕ ИЗМЕРЕН. Зона пере-сняла и опровергла его третьим независимым способом: тот же пакет с теми же флагами В ПЕРЕДНЕМ ПЛАНЕ проходит — ok 29.048s, пик 3.26 ГБ, совпал с семплером до килобайта. Убивает супервизор ФОНОВЫХ задач харнесса, переднему плану он не указ. Конкуренция была ПЯТОЙ версией причины подряд, и умерла вместе с четырьмя предыдущими (её: -p, тяжесть пакета, cgroup, нехватка памяти машины).

Что из этого норма, а что — нет.

  • НЕ норма: «гнать тяжёлое, когда рядом нет второго тяжёлого». Это суеверие; оно лечит соседа, а не причину, и записано теперь прямо в ряд 488.
  • Норма: разрешая агенту ПРОГОНЫ, ты принимаешь решение о ЧУЖОМ замере. Предупредить соседа обязан — не потому, что знаешь механизм, а потому, что проигрыш от твоей ошибки достаётся тому, кто ни о чём не просил. Форма предупреждения при этом обязана называть, что довод НЕ измерен, иначе сосед примет гипотезу за факт и будет чинить не то. Я этого не назвал — написал «может быть конкуренцией» без слов «я это не мерил».
  • Норма: убийство прогона не засчитывается вердиктом посадки. Отличать прибором: убийство — нет строки-итога, уведомление приходит как killed; падение теста — есть код возврата и строки FAIL с именами.
  • Норма: обрывать посадку на середине нельзя. Неизмеренная запись не говорит ни «поймана», ни «выжила», и стоит дороже получаса ожидания — этим доводом зона отказалась от моего предложения остановить ось.

⚠ И главное про себя: я весь день ловил чужие и свои выводы, подставленные на место замеров, — и в тот же день подставил свой. Разница между «объяснил» и «измерил» не исчезает оттого, что объяснение звучит технично.

ПРЕЖДЕ ЧЕМ РЕЗАТЬ ФАЙЛ, СЧИТАЙ ЯКОРЯ ПО ВСЕМУ РЕПОЗИТОРИЮ, А НЕ ПО СВОЕЙ ПАПКЕ (17.09)

Собирался вынести из журнала прогресса 70 строк отработавшего пинга. Посчитал якоря, целящиеся в журнал, — вышло 5, все мои, и рез выглядел безопасным. Прибор считал по docs/.

Пере-снял по всему дереву: 19 якорей из ЧУЖИХ зон — движок 3, платформа 10, полигон 3. Из них 11 целятся НИЖЕ выносимого блока (съехали бы на 70 строк) и 1 внутрь (умер бы). Чинить их я не вправе: чужие зоны, часть держателей — вообще архивы платформы, которые по канону не правятся.

Рез отменён, блок остался на месте, живое вынесено СТРОКОЙ ТРЕКЕРА (ряд 489) и указателем над пингом. Это дешевле и честнее: трекер переживает любой рез, а 70 строк фактуры никому не мешают.

Норма: файл, в который целятся чужие зоны, режется только после счёта якорей ПО ВСЕМУ РЕПОЗИТОРИЮ. Мой docs/-греп дал ложный знаменатель ровно того же рода, что ловил меня весь день: прибор спросил часть предмета и промолчал уверенно. ⚠ И частность, которая тут важнее общего правила: у выноса есть цена, которую платит не тот, кто режет. Сдвиг строк ломает ссылки чужих зон молча — гейт якорей увидит только те, у которых есть токен, а голый адрес в прозе не увидит никто.

⚠ Попутно замерено: часть чужих якорей в журнал УЖЕ мертва — доки движка целятся на строки 2880 и 1874 при журнале в 1016 строк. Это последствие моего же утреннего выноса хроники полигона, сделанного по такому же неполному счёту.

Продолжение того же часа: «НЕ РЕЗАТЬ» и «НЕ ДВИГАТЬ» — РАЗНЫЕ ВЕЩИ, и я перепутал их немедленно

Отказавшись от выноса 70 строк ради сохранности чужих якорей, я тут же вписал на то же место указатель в 11 строк — и всё, что ниже точки вставки, съехало ровно так же, как съехало бы при резе, только меньше.

Замер вреда, снятый сравнением с версией из истории (git show HEAD~2:<файл> против рабочего дерева) по десяти целям чужих якорей: пять сдвинулись, пять целы. Сдвинулись те, что лежали ниже точки вставки.

Практическая цена здесь мала — держатели сдвинутых адресов это архивы платформы (по канону не правятся) и полигон (выведен из скоупа), — но рассуждение было дырявым: я защищал якоря от реза и повредил их вставкой, потому что думал о «выносе блока», а не о «сдвиге строк». Механизм один: любая правка выше по файлу двигает всё ниже, независимо от того, добавляю я строки или убираю.

Норма: в файл, в который целятся чужие зоны, правки вносятся В КОНЕЦ либо с последующим пере-замером целей. Если правка обязана стоять в середине (как указатель у своего раздела) — это законно, но тогда цена называется вслух и замеряется сравнением с историей, а не объявляется нулевой.

⚠ И общий вывод дня, который эти два случая делают наглядным: file:line в прозе — не ссылка, а снимок. Он верен в момент написания и стареет от любой правки носителя, своей или чужой; гейт видит только те снимки, у которых есть токен, а голый адрес не стережёт никто. За смену это всплыло четырежды: переименованная строка движка, адреса в двух исследованиях, мои собственные два якоря и вот эти пять чужих.