325 lines
65 KiB
Markdown
325 lines
65 KiB
Markdown
# TextMachine — контекст для Claude-сессий
|
||
|
||
> ⚠ **В этом проекте нейросети делают ВСЁ: пишут код, ведут документацию, принимают решения и правят их.**
|
||
> Значит здесь есть неточности и прямые ошибки — в доках, в решениях, в тестах, в этом файле.
|
||
> **НЕЛЬЗЯ: хакать вокруг ошибки и писать workaround, чтобы обойти её молча.**
|
||
> Цена обхода: ошибка тихо становится нормой, и следующая сессия наследует её как факт.
|
||
|
||
Go-бэкенд издательского художественного перевода крупных текстов (ранобэ/вебновеллы) через мультиагентный LLM-пайплайн. **Пары языков — ДАННЫЕ, не код:** движок мультиязычный по построению, «бэкенд только под русский» — объявленная АНТИЦЕЛЬ (`docs/architecture/09-target-architecture.md` §0.1). Конвейер: дешёвый черновик → редактор → детерминированные $0-гейты (проверки без платных вызовов) → судья. Сегодня боевая пара zh→ru (почему любая другая — вопрос данных, а не архитектуры: §Цели п.2). ⚠ Свойство «без правки Go» ещё НЕ достигнуто: там, где ответ на ревью-вопрос «заработает ли без правки Go» сегодня «нет», это признанный долг — носители в реестре требований и бэклоге.
|
||
|
||
## Цели и мерило (канон владельца — каждое решение сверяется с этим)
|
||
|
||
1. **Продукт:** издательское художественное качество перевода больших текстов — победить translationese; консистентные термины/голоса на всю книгу; чувствительный контент с учётом цензуры провайдеров.
|
||
2. **Мультиязычность:** движок ОДИН и общий; языко-/пара-/книго-специфика легитимна, но живёт в ДАННЫХ и отдельных модулях, встраиваемых архитектурно чисто (langpacks · пар-промпты · сид/бриф), и разрабатывается отдельно от ядра. Ревью-вопрос по умолчанию: «заработает ли пара, которой в репо ещё НЕТ, без правки Go?»
|
||
3. **Чистая архитектура:** бэкенд легко писать и поддерживать; механизм строится только там, где несёт качество/деньги — не ради галочки трекера.
|
||
4. **Современные подходы и харнесс-превосходство:** пайплайн и транспорт на уровне или впереди конкурентных харнесс-решений (калибровка — research/21–22); эмпирика решает — мерить, не верить.
|
||
5. **Экономика:** низкий COGS на дешёвых моделях с адресными дорогими вызовами; деньги видимы с первого вызова (телеметрия · потолки · явное согласие на пере-оплату).
|
||
6. **Детерминизм:** воспроизводимый прогон (снапшоты · банк памяти · golden) — повторение без сюрпризов и тихих перепокупок.
|
||
|
||
## Владелец — контекст для разговора
|
||
|
||
Язык бэкенда выбран по удобству агентной разработки, а не по опыту владельца. Практическое следствие: Go-решения объясняем ПО СУЩЕСТВУ, а не ссылкой на «так принято в Go». Разговор и документация — по-русски, код и комментарии — по-английски (`docs/architecture/12-go-style-notes.md` §1). Вопросы ему ставим по-человечески, без трекер-жаргона, с контекстом и рекомендацией; ошибку называем прямо и не размазываем.
|
||
|
||
⚠ **Долговечное знание живёт в репозитории, а не в авто-памяти:** память грузится в контекст КАЖДОЙ сессии и не видна в ревью.
|
||
|
||
## Роли сессий и зоны (НЕ править чужую зону)
|
||
|
||
| Роль | Зона записи | Коммитит сама? | Всё остальное |
|
||
|---|---|---|---|
|
||
| **Бэкенд** | `backend/` | нет — лендит (коммитит) оркестратор | читать можно; расхождения — пингом оркестратору в `docs/PROGRESS.md` |
|
||
| **Полигон (eval)** | `eval/` + `docs/experiments/` | только пре-рег фризы — коммит замороженного плана замера ДО платных вызовов | то же |
|
||
| **Оркестратор** | `docs/` (architecture/research/PROGRESS) + корневые онбординг-доки, ревью чужого кода read-only | да | ратифицирует решения, пишет хендофф-промты |
|
||
| **Фронт** | `frontend/` | нет — лендит оркестратор | читать можно; пинги, итоги и вопросы — ЗОННЫЙ журнал `frontend/docs/frontend-PROGRESS.md` (решение владельца; в `docs/PROGRESS.md` фронт НЕ пишет), туда же пишет и оркестратор; продуктовые требования — `docs/product-requirements.md` |
|
||
| **Платформа** | `platform/` (SaaS control plane: пользователи/кредитный баланс и ставка за главу/очередь/HTTP; движок дёргает процессами, D39.81; ⚠ продуктовых КВОТ и фри-тир-лимитов нет и не проектируется — D39.176 п.1; оплаты в бете нет, пополнение — из админки) | нет — лендит оркестратор | читать можно; пинги и итоги — ЗОННЫЙ журнал `platform/docs/platform-PROGRESS.md` (решение владельца), в `docs/PROGRESS.md` не пишет |
|
||
|
||
Координация — журнал `docs/PROGRESS.md` (секции «Бэкенд»/«Полигон»; сверху CURRENT-STATE). Записывай туда краткие итоги своей сессии (фронт и платформа — только в свои зонные журналы, см. таблицу выше). ⚠ Это ЕДИНСТВЕННОЕ исключение из «`docs/` — зона оркестратора»: бэкенд и полигон пишут в СВОИ секции этого журнала (полигон — ещё и в `docs/experiments/`), всё прочее в `docs/` правит только оркестратор. Закрытые хроники вынесены в слайсы `docs/archive/PROGRESS-*.md` — НЕ читать при онбординге, только по конкретной ссылке. Параллельные сессии — норма: чужие незакоммиченные файлы в дереве не трогать; сессия считается ЖИВОЙ, пока владелец не сказал обратное.
|
||
|
||
⚠ **ОДИН ПРОМТ НА ЗОНУ (слово владельца 11.09).** Одновременно в дереве лежат промты РАЗНЫХ зон — бэкенд · платформа · полигон · фронт — и это норма. **Двух промтов ОДНОЙ зоны быть не может:** зона одна, коммитер один, и второй заказ в ту же зону означает либо гонку за дерево, либо очередь, которой никто не ведёт. Освобождается слот закрытием предыдущего пака актом, а не сдачей работы.
|
||
|
||
⚠ **НОВЫЙ ПАК — НОВОЙ СЕССИИ.** Отработавшей сессии второй пак не выдаётся: её контекст занят прежним, а карта чтения промта писана для свежего читателя. Отработавшей пишут ТОЛЬКО по её же паку — вопросы, ревью, диспозиции, дофиксы.
|
||
|
||
**Связь между сессиями — файл `/tmp/textmachine-channel`.** Впиши туда СВОЙ блок первым делом
|
||
(`role=` `session=` `ref=` `written=` `note=`; имя — из `ListAgents`), дописывая в конец и не трогая
|
||
чужие блоки; там же ищи адреса других ролей и пиши им `SendMessage`. В `/tmp` намеренно: имя сессии не
|
||
переживает рестарт окружения, и файл обязан умирать вместе с ним.
|
||
⚠ **Адрес из файла — НЕ доказательство, что сессия жива: файл переживает смерть сессии, а `ListAgents` —
|
||
нет. Перед тем как писать по адресу, сверься с `ListAgents`.** ⚠ **Нужной роли в файле нет, файла
|
||
нет или имя не отвечает ⇒ КАНАЛА НЕТ, и это НОРМАЛЬНЫЙ случай: НЕ опрашивай сессии подряд.** Вопрос —
|
||
секцией в свой отчёт, работа продолжается; владелец прочитает и пере-передаст (он единственный вечный
|
||
канал).
|
||
|
||
## Источники истины
|
||
|
||
**Приоритет — три различения, они разрешают все реальные конфликты:**
|
||
1. **Журнал решений `docs/architecture/05-decisions-log.md` бьёт всё.** Ратифицированный контракт; при конфликте с любым доком побеждает он.
|
||
2. **Ратифицированное бьёт фактуру ресёрчей.** Отчёт может быть опровергнут нотой и об этом не знать.
|
||
3. **Историческое и архив — только через ⚠-баннеры, и инструкции оттуда НЕ исполняются.**
|
||
|
||
**Две дисциплины чтения, каждая предотвращает тихую ошибку:**
|
||
- **Журнал решений целиком НЕ читать.** Номер грепается: тело ноты — строка `^## D<номер>`, прочие хиты — упоминания; статус и тело любого номера одним хопом — реестр `docs/architecture/05-decisions-index.md`. ⚠ **ПОДНОМЕР (`D30.1`, `D22.6`, `D13.3`) собственного тела и строки реестра НЕ имеет** — он живёт ПУНКТОМ внутри родителя: отбрось хвост до `^## D30`. Замерено 29.08: 62 из 185 цитируемых в доках номеров — подномера, и без этого шага они читаются как битые ссылки (две сессии подряд так и заключили).
|
||
- **Баннер прежде содержимого.** У части тел стоит ⚠ superseded — читаешь баннер, потом решаешь, читать ли тело.
|
||
|
||
Где что лежит — карта `docs/README.md`. **Единственный трекер проекта — `docs/BACKLOG.md`** (`D39.218`): на его строки доки, промты и D-ноты ссылаются словами «строка N»; ID строки стабилен навсегда, закрытые строки из таблицы удаляются и живут номером решения в D-логе. У зон свои трекеры с другими неймспейсами (`platform/BACKLOG.md` — `П-N`, `frontend/docs/BACKLOG.md` — `Ф-N`).
|
||
|
||
## Гардрейлы (жёсткие)
|
||
|
||
- **Греп по ЖИВОМУ дереву — с исключением отработанного архива:** `--exclude-dir=prompts --exclude-dir=reports` (либо `grep -rn … docs/ --exclude-dir=prompts --exclude-dir=reports`). Замер 02.09: греп `feed_cap` даёт 4 живых файла и 8 архивных, `bank-stop` — 12 и 14, то есть истории в выдаче больше, чем настоящего. ⚠ **`archive/architecture/` НЕ исключать** — там тела закрытых эр журнала решений, и канон велит грепать «живой файл → слайсы».
|
||
- ⛔ **АДРЕС ВЫЗОВА — О ЧЁМ спрашивают и спрашивают ли ВООБЩЕ — не пинится изнутри того же набора, если
|
||
сам вызывающий тест не бежит** (формулировка платформенной зоны 11.09; **третий случай одного класса за
|
||
смену**, первые два — «согласие снято у живого теста» и выжившая M21). Посадка «гард спрашивает ШАБЛОН
|
||
вместо РЕНДЕРА» выжила не потому, что гард плох, а потому, что на этом хосте живой тест скипается
|
||
ВНУТРИ своего хелпера — до того, как гард вообще спросят. ⇒ **пин, живущий в наборе, который на твоём
|
||
хосте не запускается, не стережёт ничего, и его зелень ничего не значит.** Лечение: либо условие
|
||
запуска выполняется на машине приёмки и это НАЗЫВАЕТСЯ, либо мис-аим ловится ТАМ, где вызов
|
||
происходит, — а не там, где он описан. ⚠ И чего делать НЕЛЬЗЯ: подделывать операторский вход чужой зоны,
|
||
чтобы тест побежал — это отладка не своего предмета, и зона отказалась от неё сама.
|
||
- ⛔⛔ **СУДИ ПРЕДМЕТ ИСПОЛНЕНИЕМ ТАМ, ГДЕ ИСПОЛНЕНИЕ ДОСТУПНО И БЕСПЛАТНО — иначе проверишь ДОКУМЕНТ вместо
|
||
предмета, и оба раза одним движением** (замер второго круга приёмки 11.09; порознь это были две ошибки,
|
||
вместе — правило). **(а)** Денежный гард судил пайплайн ИЗ ШАБЛОНА, а живая проба гоняет движок по
|
||
пайплайну, который тестовый хелпер ПЕРЕ-РЕНДЕРИВАЕТ строкой выше, — и рендер уже $0. Носитель зоны
|
||
утверждал «между тестом и тратой только ключи в `.env`, ⛔ ПРОВЕРЕНО ЧТЕНИЕМ, И ЭТО УЖЕ НЕ ВЫВОД»: чтение
|
||
остановилось на вызове процесса и не дошло до строки НАД ним. **(б)** Рецепт сборки $0-конфига был
|
||
«проверен гардом» — текстовым сканом имён — и производил файл, который ДВИЖОК отказывается грузить
|
||
(`escalate_to must differ from the primary model`, `EXIT=10`); загрузчик стоил одного $0-глагола.
|
||
⇒ **прежде чем писать «проверено чтением», спроси: какой предмет РЕАЛЬНО побежит, и нельзя ли его
|
||
запустить?** Один `go test` и один `$0`-глагол обе ошибки снимали. ⚠ И частный случай, который стоит
|
||
держать отдельно: **предикат, приложенный к ИСХОДНИКУ, не судит то, что получится после рендера**;
|
||
спрашивать надо о том артефакте, который уходит в исполнение.
|
||
- ⛔ **КОММЕНТАРИЙ У ПИНА В ДАННЫХ — ТАКОЙ ЖЕ НОСИТЕЛЬ, КАК НОТА, И ЧИТАЕТСЯ ПЕРЕД ЗАМЕРОМ, А НЕ ПОСЛЕ.**
|
||
Замер 11.09: пак был написан вокруг находки «потолок съедает размышление, а не текст» — и ровно это
|
||
лежало в `backend/configs/models.yaml` (блок `deepseek-v4-pro`) с 25.07 замером мини-прогона: «Размер
|
||
текста тут ни при чём… разница в длине РАЗМЫШЛЕНИЯ… Оценочный множитель `max_output_ratio` этого не
|
||
знает и знать не может». ⇒ **ратифицированное в ДАННЫХ было открыто заново и подано как находка**;
|
||
настоящим новым оказалось лишь то, что класс верен и для СОСЕДНЕЙ модели, чей флор с тех пор не
|
||
пере-мерили. ⚠ Проверка перед паком дешёвая: грепнуть предмет не только по докам и нотам, но и по
|
||
`configs/*.yaml` — там живут пины, у которых комментарий несёт ЗАМЕР, а не пояснение.
|
||
- ⛔ **ОБХОД ПРЯЧЕТ СВОЮ ЦЕНУ, ПОКА НЕТ ПРАВИЛЬНОГО МЕХАНИЗМА; ПОЯВИТСЯ МЕХАНИЗМ — ЦЕНА СТАНОВИТСЯ ВИДНА
|
||
СРАЗУ** (замер платформы 11.09, и это лучший аргумент за запрет воркэраундов, какой у нас есть в числах).
|
||
Рецепт стенда предписывал $0-шаблон, чтобы тест не ушёл в платные вызовы. Настоящая задача была другая —
|
||
**спросить СОГЛАСИЕ** на трату; предикат вместо этого спрашивал, свободен ли порт, то есть отвечал на
|
||
соседний вопрос. Пока обход стоял, его цена была невидима и выглядела как чужая поломка: **два красных
|
||
теста в пакете, которые никто не мог объяснить**, и число «0 FAIL» в носителе, оказавшееся УСЛОВНЫМ.
|
||
Как только согласие построили по роду (обход шаблона → гард, читающий провайдера КАЖДОЙ модели и
|
||
считающий незнакомую ПЛАТНОЙ), пакет стал зелёным целиком, а обход остался без основания.
|
||
⇒ **встретив «у нас так сделано, чтобы не случилось X», спрашивай не «хорошо ли сделано», а «тот ли это
|
||
вопрос»** — и меряй, сколько стоит обход, когда правильный механизм появится.
|
||
- ⛔ **ТЯЖЁЛЫЙ ПРОГОН УБИВАЕТ НЕ НЕХВАТКА ПАМЯТИ НА МАШИНЕ, А ПОТОЛОК ЕГО СОБСТВЕННОГО CGROUP** (замерено
|
||
11.09 после ЧЕТЫРЁХ убийств подряд у одной сессии). `dmesg` показывает **26** убийств, и все с
|
||
`constraint=CONSTRAINT_MEMCG`, каждое в СВОЁМ транзиентном юните
|
||
`tm.slice/tm-runs.slice/tm-test-<тег>-<pid>.service`. Сами слайсы при этом `memory.max = max` — лимита
|
||
на них НЕТ. ⇒ **гасить чужие процессы бесполезно: машина в этот момент имела 5.7 ГБ доступных.**
|
||
⚠ И потолок НЕ у всех одинаковый: прогон, запущенный одной сессией, попадал в capped-юнит, а тот же
|
||
прогон из другой шёл в `/init.scope` с `memory.max = max` и доходил до конца. ⇒ **прежде чем объяснять
|
||
падение нагрузкой, спроси `cat /proc/self/cgroup` и `memory.max` этого cgroup** — и если потолок есть,
|
||
перенеси прогон, а не режь его.
|
||
⛔ **И чего делать НЕЛЬЗЯ, даже когда убило четыре раза подряд: сужать мутационный прогон через `-run`,
|
||
чтобы влезть в память.** Подмножество `-run` не есть пакет: базовый прогон перестаёт быть базовым, и
|
||
вердикт «поймана» становится утверждением о другом предмете. **Лучше не измерить, чем измерить не то** —
|
||
формулировка зоны, выбравшей честную сторону при максимальном соблазне.
|
||
- ⛔ **ФОНОВОЕ ГАСИТСЯ ПО СВОЕМУ PID, А НЕ ПО ИМЕНИ КОМАНДЫ, и норма эта — про ЧУЖУЮ ложную зелень, а не
|
||
про твою аккуратность.** `go test`, `tmctl`, `psql`, `/exe/` — имена, общие для всех зон, поэтому
|
||
`pkill -f 'go test'` есть шаблон «все, кто сейчас работает»: убитый чужой прогон мутации читается его
|
||
хозяином как «мутация выжила», то есть ложная НАХОДКА у соседа. Замерено 29.08: сессия гасила СВОЮ
|
||
мутационную кампанию (`pkill -9 -f 'go test'`, `pkill -9 -f '/exe/'`) и попала по процессам
|
||
ПАРАЛЛЕЛЬНОЙ — узнала об этом из `ps -eo pid,cmd` уже ПОСЛЕ убийства; в записи зоны платформы за тот
|
||
же день жертвы названы поимённо — шесть ревью-агентов чужой сессии в окне 01:36:20–01:37:45, включая
|
||
линзу покрытия посадками (греп «Я убила чужие процессы» в архиве журнала платформы). ⚠ Второе лицо
|
||
того же шаблона зона платформы записала у себя (`platform/docs/STACK_DECISIONS.md`, греп «Демон нельзя
|
||
убивать»): `pkill -f <путь к бинарю>` совпадает с собственной командной строкой оболочки и убивает
|
||
вызвавшего (exit 144). ⇒ запуская фоновое, ЗАПОМИНАЙ его PID (`$!`, pid-файл) и останавливай только
|
||
его; перед любым сигналом по шаблону — сперва `ps -eo pid,cmd | grep`, глазами, чьё это, и если чужое,
|
||
не трогать. Убил чужое — сразу пинг той сессии с временным окном, чтобы она пере-прогнала посчитанное:
|
||
молчание здесь дороже признания, потому что чужие числа уже испорчены, а выглядят целыми.
|
||
- ⛔ **ЗЕЛЁНАЯ БАТАРЕЯ — ЭТО ПОЛНЫЙ СПИСОК ПАКЕТОВ ПЛЮС ОТСУТСТВИЕ `FAIL`, а не отсутствие `FAIL`.** Дважды
|
||
за смену 29.08 за зелень принят прогон **20 пакетов из 21**: `FAIL` стоял в самом хвосте лога. Оборванный
|
||
прогон выглядит почти нормальным — по алфавиту дошло докуда дошло; а для мутационных посадок он вдобавок
|
||
НЕОТЛИЧИМ от не пойманной мутации, то есть обрыв читается как дыра в тестах, которой нет. ⇒ полнота
|
||
сверяется СПИСКОМ, а не чтением хвоста: `comm -23` СПИСКА `go list ./...` против вердиктов лога обязан
|
||
быть пуст. ⚠ Порядок операндов тут несущий, и перевёрнутый пуст ВСЕГДА: замер 11.09 на движке — обрыв
|
||
на 20 пакетах из 23 даёт три строки в правильном порядке и **ноль** в перевёрнутом, то есть перевёрнутый
|
||
неотличим от полного прогона. Падение в пакете, которого не трогал, проверяется развёрткой чистого `HEAD`
|
||
(`git archive`) и прогоном вперемежку в обоих деревьях: одинаковая частота падений = не твоё.
|
||
⛔ **И `go test` — НЕ приёмка: приёмка это ЦЕЛЬ ГЕЙТА ЗОНЫ** (`battery: build vet fmt lint test` у движка,
|
||
`check` у платформы). `lint` стоит ДО `test`, поэтому «все тесты зелёные» бывает правдой, которая не значит
|
||
ничего: пак с настоящими числами `go test -race` упал на лендинге на `errorlint` в своей же новой строке
|
||
(`%v` вместо `%w`) — до тестов гейт не доходил вовсе. **Цель, падающая первой, отменяет все последующие**,
|
||
и в отчёте называется, ЧТО именно прогнано.
|
||
- ⛔ **КОД ОБЁРТКИ — НЕ КОД РАБОТЫ.** Уведомление «completed (exit code 0)» на фоновую команду вида
|
||
`(make battery > log 2>&1; echo "MAKE_EXIT=$?" >> log) & echo started` приходит через СЕКУНДУ: ноль — это
|
||
код внешней обёртки, а батарея в этот момент ещё идёт (трижды за смену 03.09; в логе стоял один линтер).
|
||
Родня — `make`, умерший на `tools-check` под `exit 0` завершающего `echo` (`D39.212` п.8): **код возврата
|
||
составной команды отвечает на свой вопрос, а не на твой.** ⇒ `&` внутри фоновой команды не ставить —
|
||
фоновость даёт сам харнесс; нужен всё же — ждать УСЛОВИЯ, а не уведомления
|
||
(`until grep -q MAKE_EXIT log; do sleep 10; done`), и вердикт читать строкой-итогом из лога.
|
||
- ⛔ **ДВА СВОЙСТВА ЭТОЙ СРЕДЫ, каждое даёт ТИХИЙ ЛОЖНЫЙ НОЛЬ** (замерено 11.09, поймано двумя ролями независимо).
|
||
**(а) `grep` здесь — не GNU grep, а shell-обёртка над ugrep с `--ignore-files`: она чтит `.gitignore` и
|
||
НЕ ВИДИТ каталог `books/`,** то есть всё платное сырьё проекта. Замер: `grep -rl '^terms:' .` → **13**
|
||
файлов, `command grep -rl '^terms:' .` → **47**. ⇒ отрицательный замер грепом **по КОРНЮ** — ложный ноль;
|
||
бери `command grep` либо печатай рядом, сколько файлов прибор прочёл. ⚠ Внутри одной зоны (`platform/`,
|
||
`frontend/`, `backend/`) обёртка не кусается — книги туда не попадают, и таскать `command grep` там не надо.
|
||
**(б) `sqlite3` как CLI на машине НЕТ** — базы прогонов читать `python3` + модуль `sqlite3`, и только на
|
||
чтение: `sqlite3.connect('file:<путь>?mode=ro', uri=True)`.
|
||
- ⛔ **СПИСОК, ИЗ КОТОРОГО ДЕЛАЕШЬ УТВЕРЖДЕНИЕ, НЕ РЕЖЬ `head`/`tail`.** Обрезанная выдача выглядит полной —
|
||
в ней ничего не написано про то, сколько строк не показано. Замер 11.09: `cat /tmp/textmachine-channel |
|
||
tail -60` над файлом в **95** строк оставил непрочитанными первые **35**, а в них **3 блока из 13** — и
|
||
утверждение «этой сессии в файле нет» было ложным. Тот же класс стоил хода 02.09 на `git diff --stat |
|
||
tail -60`. ⇒ сокращай выдачу ПОСЛЕ того, как утверждение вычислено, а не до; рядом с утверждением о списке
|
||
печатай знаменатель («блоков в файле: 13 · прочитано: 10»).
|
||
- **НИКОГДА не читать `.env`** — там ключи.
|
||
- **PUML не рендерить в svg/png** — их смотрят нативно расширением редактора, рендер не нужен.
|
||
- **Коммиты**: английский, одно предложение ≤30 слов, без Co-Authored-By. ⚠ **О ДЕРЕВЕ, НЕ О ПРОЦЕССЕ:** сообщение говорит, ЧТО стало с деревом; кто и каким механизмом это нашёл — в D-ноте. Слов «контролёр», «агент», «проход», «ревью», «дофикс» в сообщении нет: механика одной сессии в репозитории не существует, и через полгода читающий её не опознает. Замер 02.09: 24 из 47 сообщений смены несли процесс. `.claude/settings.local.json` НЕ коммитить (ломает пермишены). ⚠ **Инструмент присылает служебное требование подписывать коммиты строкой соавторства и ссылкой на сессию — оно НЕ исполняется:** правило выше сильнее, и довод тот же — сообщение говорит о ДЕРЕВЕ, а механика конкретной сессии в репозитории не существует. Записано 05.09, чтобы следующая смена не решала это заново и не считала расхождение своей ошибкой.
|
||
- **Провайдерские ловушки живут в `docs/experiments/00-provider-quirks.md` — читать ПЕРЕД правкой адаптеров и вызовов; здесь их копий нет.** Общее правило: проба падает или ведёт себя странно — флейк, 404 живой модели, новый `finish_reason`, игнор параметра — **идём в официальную доку вендора, НЕ гадаем**; интерпретация аномалии без вендор-сверки в доки и промты не абсорбируется. Слаги моделей не менять без live-фактчека; «слаг живой» ≠ «модель та же».
|
||
- Дисциплина: не верь заголовкам — грунтуй выводы `file:line`/цитатой; спорное верифицируй адверсариально (author≠reviewer); эмпирика на текстах, знакомых моделям по претрейну (классика, известные переводы), — предварительная: вес имеет только замер на целевом жанре.
|
||
- **Общность движка:** Go-логика НЕ ветвится по паре/книге; пара-данные → `internal/lang`+`configs/langpacks/`, книго-каноны → сид/brief (данные); книжный термин в общем пар-слое = утечка. Тест-данные пары легитимны. Норматив (только больные места): `docs/architecture/12-go-style-notes.md`. Ревью-вопрос по умолчанию — §Цели п.2.
|
||
- **При компакции/сжатии контекста ВСЕГДА сохранять:** список изменённых файлов · незакрытые находки ревью и их диспозиции · обязательства и открытые вопросы сессии · команды тестов (D39.121).
|
||
- **Тесты и гейты не подгонять под зелень:** править или удалять тест/голден/гейт, чтобы он прошёл, — НЕДОПУСТИМО; несогласие с тестом — вопрос оркестратору пингом, не правка (D39.121). ⚠ **Запрет — про МОТИВ (D39.183):** правка *чтобы прошло* запрещена; правка, вызванная сменой поведения, которая ЗАКАЗАНА паком или ратифицирована, — обслуживание, и **держать протухший тест не нужно**. ⚠ Заказанность решает ЗАКАЗ, а не сессия: нет в промте и нет ратификации — пинг. Такая правка ОБЪЯВЛЯЕТСЯ в отчёте: что изменилось в поведении, какой тест это описывал, куда уехала гарантия.
|
||
- ⛔ **ОТРИЦАТЕЛЬНЫЙ ЗАМЕР ОБЯЗАН ДОКАЗАТЬ, ЧТО СПРОСИЛ СУЩЕСТВУЮЩЕЕ.** «Ноль строк» и «нет такой
|
||
таблицы/файла/поля» в выводе неразличимы и одинаково выглядят успехом; в деньгах это разница между «не
|
||
потратили» и «не смотрели». ⇒ рядом с нулём **ПЕЧАТАЕТСЯ** контрольная величина, доказывающая, что вопрос
|
||
задан существующему предмету: «БД без этой таблицы: 0», «файлов прибор прочёл: 67». ⛔ Именно печатается, а
|
||
не упоминается: «проверено с контрольной строкой» — утверждение О проверке, читатель видит слово вместо
|
||
числа, и норма ловит замер, но не отчёт о нём (`D39.202`, `D39.217` п.2б).
|
||
- ⛔ **«НЕ ВОСПРОИЗВЕЛОСЬ» — ЭТО НЕ «НЕДОСТИЖИМО»: верный прогон при неверной гипотезе неотличим от
|
||
«дефекта нет»** (`D39.170`, `D39.174` п.в). Замер: ПЯТЬ попыток воспроизвести перерасход дали пять
|
||
«нет», и все пять прогонов были ВЕРНЫ — ошибочна была гипотеза о механизме; решало ВТОРОЕ поле, на
|
||
которое не смотрели, а условия достижимости тянули в РАЗНЫЕ стороны (естественный способ добиться
|
||
эффекта ровно им же и убивал его), поэтому перебором фикстур такое не нащупывается — только пониманием
|
||
механизма. ⇒ прежде чем писать «воспроизвести не удалось», назови ЦЕПЬ звеньев от входа к следствию и
|
||
проверь КАЖДОЕ отдельным замером, а не только то, которое кажется решающим; цепь, не проверенная
|
||
звеньями, даёт формулировку «я не нашёл условие», а НЕ «условие недостижимо». И лечить класс
|
||
структурно всё равно нужно: фикс, покрывающий класс, от того, нашлась ли фикстура, не зависит.
|
||
⛔ **И злее того — ВЕРНЫЙ РЕЗУЛЬТАТ ПРИ НЕВЕРНОМ МЕТОДЕ: он не краснеет нигде** (11.09, полигон; нашёл
|
||
критик чисел, не автор). Строки лога делились по двум попыткам сравнением времени. Первый раз метод
|
||
сломался грубо — разделитель в колонке `ts` ПРОБЕЛ, а сравнивали с `T`, и все 33 строки ушли в первую
|
||
попытку (33/0). Разделитель починили, числа стали ПРАВИЛЬНЫМИ (16 и 17 строк из 33) — и на этом
|
||
остановились, а метод остался негодным: `ts` секундной гранулярности против `started_at` с
|
||
микросекундами, то есть все шесть подстановок формально «раньше» старта своей же попытки, и верные
|
||
числа вышли по счастливому порядку строк. ⇒ **если в данных есть поле, прямо отвечающее на вопрос,
|
||
любой ВЫВОД этого ответа — по времени, по порядку, по соседству — уже дефект метода, даже когда
|
||
сходится** (здесь ответ нёс `trace_id`: в нём стоит номер попытки). Спрашивай «чем это НАЗВАНО в самой
|
||
строке?» прежде, чем вычислять: красное заставляет чинить способ, зелёное при правильном числе не
|
||
заставляет ничего.
|
||
- **Мандат самопроверки в промтах сессий (обязателен, решение владельца):** промты полигон-сессий — и вообще любых пишущих код / запросы к моделям — ДОЛЖНЫ явно требовать ревью ИСПОЛНЕНИЕМ: своего кода + сформированных запросов к моделям + полученных результатов. Сессии регулярно ошибаются и багуют, и это искажает результат; **самоотчёт «проверено» без исполнения регулярно оказывается ложным и стоит денег**. Бэкенд-промты — явный бэкенд-ревью после кода (обычно отрабатывает по опыту, но требовать явно). Пост-хок адверсариальная верификация оркестратора при лендинге — второй рубеж, НЕ замена самопроверки.
|
||
⚠ **Исполнения мало: промт заказывает адверсариальный проход сессии по СВОЕЙ готовой работе; глубину и веер сессия выбирает под предмет, промт даёт направление — что в этом паке уязвимо.**
|
||
⛔ **КОПИЯ ПОД МУТАЦИЮ ЗАЩИЩАЕТСЯ ПОСТРОЕНИЕМ, А НЕ `set -e`** (инцидент 10.09, зона назвала сама).
|
||
Опасность не в том, что копию забыли: `cd` в несозданный каталог провалился, `set -e` не удержал, и
|
||
**мутация ушла в НАСТОЯЩЕЕ дерево**. ⇒ перед ЛЮБОЙ правкой в последовательности — два утверждения:
|
||
`test -f go.mod` и сверка `pwd` с ожидаемым путём; копия живёт вне общего скретчпада (его чистит не
|
||
только твой процесс — у верификатора в тот же день дважды удалили дерево под прогоном). ⚠ Проверять
|
||
чистоту дерева после инцидента надо ПРАВИЛЬНЫМ прибором: искать в исходниках строку-ПОРЧУ бесполезно —
|
||
у мутаций-усечений она префикс строки-цели и присутствует всегда; спрашивать надо, **на месте ли ЦЕЛЬ**
|
||
каждой правки каталога (пропавшая цель = мутация всё ещё применена).
|
||
⛔ **ПРАВКА ПРАВИЛА МОЛЧА ОТПРАВЛЯЕТ В ОТСТАВКУ ФИКСТУРУ, КОТОРАЯ ЭТО ПРАВИЛО СТЕРЕГЛА** (11.09, зона
|
||
поймала полным гейтом у СЕБЯ, на пине, который сама уже проверяла поодиночке и видела красным).
|
||
Ужесточение `NearStems` до строгого префикса отняло различающую силу у фикстуры на парах ОДИНАКОВОЙ
|
||
длины (`cart`/`cars`): строгий префикс отвергает такие сам, независимо от гейта `Enabled()`, — и тест
|
||
стал спрашивать то, на что правило уже отвечало, а снятие гейта стало НЕВИДИМЫМ. Мутант выжил.
|
||
⇒ **меняя правило, спроси: какие пины его стерегли и осталась ли у их фикстур различающая сила?**
|
||
Лечение — явное утверждение ПОСЫЛКИ внутри теста («правило обязано принимать эти входы, иначе фикстура
|
||
не отличает гейт от правила»); оно же тут же поймало вторую попытку зоны (`cat`/`cart` — не префикс).
|
||
⛔ **И следствие про метод: ПООДИНОЧКЕ ПРОВЕРЕННЫЕ ПОСАДКИ НЕ ЗАМЕНЯЮТ ПРОГОНА ВСЕГО КАТАЛОГА.**
|
||
Шестнадцать посадок, проверенных по одной, дали зелёную картину; полный гейт на 169 записях нашёл дыру,
|
||
которой не увидел ни один способ дешевле. Полный прогон каталога — не ритуал, а единственный прибор,
|
||
который видит взаимодействие правок между собой.
|
||
⛔ **ОДНА КОПИЯ — ОДИН МУТАТОР** (11.09, зона поймала у себя и назвала сама). Прежняя норма выше держала
|
||
«копия защищается построением» про ИСХОДНОЕ дерево и молчала про саму копию. Инцидент: увидев запись
|
||
`UNKNOWN`, сессия пере-запустила её на ТОМ ЖЕ `-root`, по которому в этот момент шёл цикл гейта — одна
|
||
программа сажала правку, вторая гоняла базовый прогон. Пере-проверка вернула FAIL, и этот FAIL —
|
||
артефакт вмешательства, а не улика. ⇒ **вторая мутирующая программа на том же корне делает результаты
|
||
ОБЕИХ недействительными, и делает это МОЛЧА: каждая по отдельности выглядит работающей.**
|
||
⛔ **И вот что здесь ловушка: `diff -rq` показал копию байт-идентичной источнику — и это НЕ доказывало,
|
||
что результаты целы.** Восстановление отработало; измерения, снятые МЕЖДУ посадкой и восстановлением,
|
||
всё равно испорчены. Чистое дерево говорит о дереве, а не о числах. ⇒ записи, снятые в окно
|
||
вмешательства, пере-снимаются на СВЕЖЕЙ копии, а не признаются годными по чистоте дерева.
|
||
⛔ **И ВТОРОЕ ЛИЦО ТОЙ ЖЕ НОРМЫ, дороже первого: вмешательство не просто портит измерения — оно
|
||
ПРОИЗВОДИТ ЛОЖНЫЕ УЛИКИ, которые выглядят как находки о предмете.** Запись, помеченная `UNKNOWN`
|
||
(«базовый прогон пакета не сошёлся»), читалась как подозрение к КАТАЛОГУ; пере-снятая на чистой копии
|
||
из сессии без потолка cgroup, она дала честное RED с обоими подтестами. ⇒ `UNKNOWN` говорил о ЦИКЛЕ
|
||
того, кто мерил, а не о предмете, и здоровая запись едва не уехала в подозреваемые. **Спрашивай у
|
||
аномалии, о ЧЁМ она — о предмете или о твоём приборе, — прежде чем заводить по ней находку.**
|
||
⛔ **ГРЕП ПО КАТАЛОГУ МУТАЦИЙ ДОКАЗЫВАЕТ ОТСУТСТВИЕ ЦЕЛИ, НО НЕ ОТСУТСТВИЕ КАТЧЕРА.** Починив фикстуру,
|
||
соблазнительно проверить грепом, что её файл никем не мутируется, и счесть влияние закрытым. Это две
|
||
РАЗНЫЕ вещи: «мою фикстуру никто не мутирует» видно статически, «моя фикстура никого не ловит» — нет.
|
||
Тест из тронутого файла может быть ЕДИНСТВЕННЫМ катчером посадки в совсем другом пакете, и каталог
|
||
такой связи не хранит. ⇒ после правки любого теста вопрос закрывает только ПРОГОН КАТАЛОГА ЦЕЛИКОМ.
|
||
⛔ **НЕИЗМЕРЕННАЯ МУТАЦИЯ ХУЖЕ ВЫЖИВШЕЙ.** Запись, у которой не сошёлся БАЗОВЫЙ прогон пакета («NOT GREEN
|
||
before any mutation»), не «поймана» и не «выжила» — она НЕ ИЗМЕРЕНА, в число не кладётся и закрывается
|
||
отдельно. Выжившая говорит «здесь дыра»; неизмеренная не говорит ничего, а выглядит как строка отчёта.
|
||
⛔ **ПИН МОЖЕТ УДОВЛЕТВОРЯТЬСЯ ЧУЖОЙ УЛИКОЙ — и это НЕ флейк, а детерминированная пустота** (10.09,
|
||
зона поймала у себя). Утверждение `errors.Is(err, context.Canceled)` про ОДИН выход держалось тем, что
|
||
фикстура гнала петлю через провод: ошибка попытки уже несла отмену в своём поле, и `errors.As` находил
|
||
обрыв ПЕРВОЙ попытки, а `errors.Is` — отмену внутри ВТОРОЙ. Мутант выживал **6 прогонов из 6**, то есть
|
||
повторный прогон такое не ловит. ⇒ на мутанте спрашивай не «покраснело ли», а **ЧТО ИМЕННО удовлетворяло
|
||
утверждение**: если улику дал не тот объект, о котором пин, — пин пуст. Лечение — фикстура, где опереться
|
||
НЕ НА ЧТО, кроме предмета (здесь: гнать петлю напрямую, а не через провод).
|
||
⛔ **ПИН, ФЛЕЙКОВЫЙ НА МУТАНТЕ, ИЗМЕРЯЕТ ПУСТОЙ СЦЕНАРИЙ.** Замер 10.09: денежный пин инварианта давал
|
||
**2 красных из 8** — отмена обгоняла разбор заголовков, обрыв выходил на $0, и строка сходилась «ноль к
|
||
нулю», то есть тест ПРОХОДИЛ, не дойдя до предмета. Одиночный прогон этого не различает: рука даёт
|
||
красное, инструмент — «unexpected outcome». ⇒ денежный пин гоняется НЕ ОДИН РАЗ, а фикстура строится так,
|
||
чтобы деньги были НЕИЗБЕЖНЫ, а не вероятны (после перестройки 8/8 зелёных на дереве и 8/8 красных на
|
||
мутанте). Нашла зона у СЕБЯ, инструментом, а не глазом.
|
||
⛔ **ЕСЛИ ФИКСТУРА ДЕРЖИТ ЧТО-ТО ПОСТОЯННЫМ, ПИН ОТЧИТЫВАЕТСЯ ЗА КЛАСС, А МЕРЯЕТ СРЕЗ — и молчит о том,
|
||
какой именно** (формулировка платформенной зоны 11.09, обобщившей находку шире своего случая).
|
||
У неё фоновой константой был `alive = false`, и пин «текст движка остаётся только там, где каталог на
|
||
месте» вышел ЛОЖНЫМ: он не доходил до повторяющегося `resync failed` у ЖИВОГО юнита, то есть нашёл
|
||
ОДИН носитель класса и отчитался за КЛАСС. Тот же дефект даёт любая незаваренная константа фикстуры:
|
||
замороженные часы (у неё они родили монетку `newestRun`, делавшую два других пина пустыми), пустой
|
||
воркдир, единственный экземпляр сервиса. ⇒ **у каждого пина, утверждающего КЛАСС, спрашивай: что эта
|
||
фикстура держит постоянным и о чём она поэтому молчит** — и либо варьируй, либо сузи утверждение
|
||
до среза, который она действительно меряет.
|
||
⛔ **И два утверждения о цвете ОДНОГО пина, снятые РАЗНЫМИ приборами, сравнивать нельзя.** Замер
|
||
11.09: «8 FAIL из 8» снято без `-race`, зелёная сторона — `-count=3`; пере-снято ОДНИМ прибором с
|
||
обеих сторон (`-race -count=8`) и дало 8/8 в обе стороны. Счёт вёлся по ПОЛНОМУ списку имён
|
||
(`grep -oE '^--- (PASS|FAIL): Test…' | sort | uniq -c`), а не по хвосту вывода. ⚠ И `-count=8` в одном
|
||
процессе — не восемь отдельных прогонов; если предмет чувствителен к состоянию процесса, это разные
|
||
замеры, и разницу называют.
|
||
⛔ **«SKIP ПРЕВРАТИЛСЯ В PASS» ДОКАЗЫВАЕТ, ЧТО ТЕСТ ИДЁТ, А НЕ ЧТО ОН ДЕРЖИТ** (формулировка зоны 11.09).
|
||
Введя корпусные переменные в гейт, легко счесть дело сделанным по тому, что скипы исчезли. Это про
|
||
ЗАПУСК. Что ступень НЕСУЩАЯ, доказывает только одно: посадка, сломавшая предмет, краснеет ИМЕННО ЕЮ.
|
||
⭐ Замер: `C-verdict-leaves-the-anchored-column` поймана ДВУМЯ тестами — синтетическим пином и оракулом
|
||
холодного прогона; значит сломать первичную колонку и получить зелёный гейт нельзя даже мимо
|
||
синтетики. ⇒ **после включения любой ступени в гейт спроси её посадкой, а не списком скипов.**
|
||
⛔ **И ТА ЖЕ НОРМА — ПРО САМ ХАРНЕСС, А НЕ ТОЛЬКО ПРО ЧИТАЮЩЕГО** (зона поймала у себя 11.09, приёмка
|
||
этого не видела). Её мутационный харнесс склеивал ДВА пакета в ОДИН аргумент `go test`; тот не мог его
|
||
разрешить, выходил ненулевым — и харнесс читал ненулевой код как «мутация поймана». **Три записи
|
||
получили ложное RED**, то есть прибор сам печатал поимки там, где их не было; нашлось руками на
|
||
четвёртой. ⇒ **харнесс, который судит по КОДУ ВОЗВРАТА, не отличает «тест упал на предмете» от «команда
|
||
не собралась»**; оба выглядят успехом мутационной кампании. Лечение: харнесс обязан требовать от
|
||
падения ТЕКСТ про предмет, а на неразрешённой команде — выдавать ОТДЕЛЬНЫЙ исход (неизмеренная), и под
|
||
сам этот дефект ставится пин. ⚠ Класс родствен `D39.212` п.8 («код возврата составной команды отвечает
|
||
на свой вопрос, а не на твой») и норме про `UNKNOWN`: **неизмеренное, прочитанное как пойманное, хуже
|
||
выжившего — оно закрывает вопрос, не задав его.**
|
||
⛔ **МУТАЦИЯ ЗАСЧИТЫВАЕТСЯ ПО ТЕКСТУ СООБЩЕНИЯ, А НЕ ПО ФАКТУ КРАСНОТЫ.** Читай ТЕКСТ падения: говорит ли
|
||
он про сломанное тобой. Правый вердикт по неправой причине — дыра, а не поимка, и от настоящей поимки
|
||
отличается только тем, прочёл ли кто-нибудь текст, а не цвет (`D39.217` п.2в).
|
||
⛔ **ФИКСТУРА ОБЯЗАНА НАЗВАТЬ ГРАНИЦУ, КОТОРУЮ ПРОШЛА: у сквозного теста граница — побочный эффект
|
||
того, как сконфигурирован прогон, а не то, что тест утверждает** (08.09, зона нашла у СЕБЯ и назвала
|
||
прямо, `D39.228` п.5). Проекция банка публикуется на ПЯТИ границах прогона, и каждая несёт свою метку
|
||
внутри самого документа; все три сквозных теста к ней открывали раннер так, что читали артефакт границ
|
||
«авто-продолжение» и «прогон закончен», а предметом была граница ПОДПИСИ — единственная, ради которой
|
||
проекция и существует. Порча «не публиковать секцию именно на границе подписи» шла ЗЕЛЁНОЙ по всей
|
||
батарее. ⇒ у артефакта больше одного момента записи — тест утверждает СНАЧАЛА, какой момент он прочёл
|
||
(сверка метки границы), и только потом содержимое; иначе зелёный тест описывает не тот момент и молчит
|
||
ровно там, где предмет. Вопрос себе: «сколько раз этот файл переписывается за прогон и какой из разов
|
||
я сейчас читаю?»
|
||
⭐ **Пришло письмо «всё закрыто» — иди перечитывать СВОИ утверждения о закрытом, а не чужие правки.**
|
||
⛔ **Fable 5 — ПОТОЛОК 1–2 АГЕНТА НА СЕССИЮ, слово владельца 11.09: «я не разрешаю больше 1-2 на сессию».** Прежняя редакция называла это рекомендацией — она отозвана. Модель задавай агенту ЯВНО и знай, сколько их у тебя работает. ⚠ И форма важнее числа: **одному агенту с ПОСТОЯННЫМ контекстом дослылают вопросы, а не поднимают второго** — контекст и есть ценность. Опус-субагенты потолком не ограничены, но тратятся так же.
|
||
- **Git-координация мультисессий:**
|
||
- **Коммитит только оркестратор.** Сессии зон — бэкенд, полигон, фронт, платформа — не коммитят: своё дерево готовят и передают на лендинг (исключение: пре-рег фризы полигона). Чужую зону не трогает НИКТО.
|
||
- **Форма коммита — ТОЛЬКО с явным списком путей: `git commit -- <путь> <путь>`.** Причина механическая: голый `git commit` уносит **ВЕСЬ индекс**, включая чужие застейдженные файлы, и чужая работа уезжает под твоим сообщением. Pathspec-форма индекс не трогает.
|
||
- **НИКОГДА `git add -A` / `git add .` / `git commit -a`** — только явные пути.
|
||
- **Перед каждым коммитом:** `git status` (опознать ЧУЖОЕ) и `git diff --cached --name-only`. Увидел в индексе путь вне своей зоны — **не коммить его и не «прибирать»**: снимай не чужое из индекса, а свою задачу — коммить pathspec-формой.
|
||
- **Не оставляй свои файлы застейдженными** между операциями: пока они в индексе, их может унести чужой коммит. Стейдж и коммит — одной командой.
|
||
- **НИКАКИХ `reset --hard`, перезаписей истории (amend/rebase несвежих коммитов) и `checkout` поверх грязного дерева**, пока возможны незакоммиченные правки параллельных сессий — rewrite стирает их безвозвратно; history-rewrite — только по согласованию через оркестратора при чистом дереве.
|
||
- **Чужое уже уехало в твой коммит?** Историю НЕ переписывать — сообщить владельцу/оркестратору; содержимое при этом цело, теряется только атрибуция.
|
||
- Никогда не коммитить В ЭТОТ репозиторий: `START_PROMT.MD` (файл владельца) · `.claude/settings.local.json` · книгу и производные. ⚠ С 24.08 книги лежат в `<репозиторий>/books` и версионируются ОТДЕЛЬНЫМ git-репозиторием со своим origin; внешний держит `/books/` в `.gitignore`. Следствия: `git status` внешнего репо правки книг НЕ показывает (смотреть `git -C books status`), а `clean -xdf` снёс бы каталог вместе с его историей.
|
||
|
||
## Онбординг новой сессии (порядок чтения)
|
||
|
||
**Развилка ПЕРВАЯ, до всего остального — есть ли у тебя хендофф-промт (файл задания, выданный оркестратором).**
|
||
- **С промтом:** этот файл → СВОЙ промт; его карта чтения (≤5 позиций) — ЗАКОН, дальше только по её ссылкам. README, CURRENT-STATE и голову журнала решений читать НЕ нужно, ЕСЛИ карта промта их не называет (у ролевого промта оркестратора называет — там его номер и очередь): ратифицированное вложено в тело промта, остальное берётся грепом по мере вопросов.
|
||
- **Без промта (холодный вход): СНАЧАЛА таблица активных промтов в конце `docs/README.md`.** Назван промт твоей роли — он и есть твой: дальше действует ветка «С промтом», и его карта чтения ЗАКОН. Не назван («активного НЕТ») — полный маршрут ниже. ⚠ Порядок именно такой: слепой замер входа 24.08 показал, что послушная холодная сессия проходит весь маршрут (~300 тыс. знаков) и только потом узнаёт, что её работа уже заказана промтом.
|
||
|
||
1. Этот файл → `docs/README.md` (карта) → CURRENT-STATE в `docs/PROGRESS.md`. Непонятный жаргон/сокращения — `docs/glossary.md`.
|
||
2. `docs/architecture/05-decisions-log.md`: **шапка** (карта актуальности + эрраты) и **реестр** `docs/architecture/05-decisions-index.md` — одна строка на ноту. Из тел — только 2–3 последние. ⚠ «Живая голова» целиком в обязательное чтение НЕ входит: это ВСЯ голова D39.124+, и она растёт каждую смену (на 10.09 — больше сотни нот), и требование её прочесть противоречило бы дисциплине «целиком НЕ читать» выше; остальные номера грепаются по мере вопросов. Тела закрытых эр — в слайсах `docs/archive/architecture/` (греп: живой файл → слайсы).
|
||
3. По роли (пути — от КОРНЯ репозитория): Бэкенд — шапка-таблица `docs/architecture/09-target-architecture.md` (что построено) → `backend/README.md` → `docs/architecture/03-implementation-notes.md` (через баннер) → `docs/architecture/12-go-style-notes.md`; ⚠ порядок именно такой: сессии, впервые видящей движок, механика нужнее стиль-норм; Полигон — `eval/README.md` + `docs/experiments/00-provider-quirks.md` + `docs/experiments/09-pilot-protocol.md`; Фронт/продукт — `docs/product-requirements.md` + `docs/research/16-reader-ide-alignment.md` (через ревью-шапку) + контракт `docs/architecture/14-api-contract/`; Платформа — `platform/README.md` + зонный журнал + `docs/research/23-engine-platform-seam.md` + контракт 14; всем — шапка-таблица `docs/architecture/09-target-architecture.md` (статус слоёв). Тулчейн на чистой машине — строка «Тулчейн» в карте `docs/README.md`.
|