docs(skill): принцип «мастер решает», готовые boilerplate-промпты, ревизия

- Зачем:
  - ретро прогона 2026-07-12 (задача 20, clickstream-demo): контекст
    оркестратора съедали инлайн-диагнозы, переписывание boilerplate и
    кириллица в обменных файлах.
- Что:
  - SKILL.md: принцип «мастер решает — субагенты выясняют» со стоп-краном
    «сам — максимум один заход», обменные файлы на английском, сквозная
    проверка до ревьюеров, будильник одной строкой.
  - references/prompts/: готовые английские boilerplate-файлы (мандат
    ревью, триаж, перепроверка) — подшиваются cat'ом, контекст мастера
    не проходят; prompt-templates перестроен под сборку.
  - codex-exec: модель gpt-5.6-sol, лестница эффорта, ловушка «&»;
    sandbox-справочник переименован в codex-sandbox-apparmor.md;
    lessons дистиллирован, добавлена запись прогона 2026-07-12.
  - закрыты 14 находок слепого Fable-ревью скилла (согласованность,
    единый источник $SCRATCH, скелет ревью постановки).
- Проверка:
  - все внутренние ссылки резолвятся; слепое ревью: APPROVED_WITH_MINORS,
    восстановление структуры подтверждено без потерь.
This commit is contained in:
ddadmin committed 2026-07-12 22:17:59 +03:00
1 parent 60182ab493
commit 7110a075ea
9 files changed
+357 -410

No files matched your search

@@ -6,228 +6,108 @@
поглощён SKILL.md или references, сжимай его запись здесь до строки-факта
(дата, что случилось, куда поглощено) — иначе файл растёт бесконечно.
## 2026-07-06 — t2-ml-forecast, задача 05 «полировка витрины под демо»
## 2026-07-06 — t2-ml-forecast, задача 05 (первый прогон; дистиллировано 2026-07-12)
Первый прогон конвейера. Задача: ~200 строк правок в ядре отчёта + ноутбук.
- Свежий взгляд на постановку окупился: блокер name_ru (в данных — английский),
две «одностроки» с проектными решениями, дыра регенерации `.ipynb`.
Поглощено: SKILL.md этап 2.
- Казус форвардера: субагент, получив постановку вместо команды, реализовал
задачу сам (+1227 строк). Поглощено: SKILL.md этап 3, codex-exec (раннер).
- Слепое двойное ревью: пересечение находок — ноль; Клод подтвердил математику
и артефакты, Codex нашёл две дыры в тестах. Поглощено: SKILL.md (роли).
- Смерть фонового ревьюера без доставленного отчёта; транскрипт не спас.
Поглощено: SKILL.md этап 4 (вердикт — файлом, сообщение — указателем).
- Цифры: ревью постановки ~60k токенов; конвейер ~3 часа, реализация ~20 мин.
**Свежий взгляд на постановку (Клод, adversarial-reviewer) — окупился:**
- блокер: постановка требовала «русские названия из `report.name_ru`», а в
данных `name_ru` — английские имена из Excel-книги; исполнитель молча
сделал бы английские заголовки. Решение внесено в задачу: словарь
«статья → русское имя» как явная поставка;
- две «одностроки», прятавшие проектные решения: поворот отрицательного ряда
(правило, пересчёт коридора, единый хелпер) и согласованность
«график по модулю vs таблица со знаком»;
- процессная дыра: без явных двух шагов регенерации `.ipynb` остался бы без
выводов, и тест ноутбука его бы завернул.
## 2026-07-07 — наглядность витрины (полный конвейер; дистиллировано 2026-07-12)
**Казус форвардера:** субагент `codex:codex-rescue`, получив постановку
вместо команды, реализовал задачу сам (+1227 строк). Настоящий Codex стартовал
на уже изменённом дереве — столкновения избежали везением (форвардер успел
закончить). Урок в SKILL.md и codex-exec.md (раздел про раннера).
- Idle-уведомление ≠ отчёт; голый поллер вне run_in_background умирает при
смене хода; статус job — не истина (зомби «running» после смерти воркера:
истина — mtime артефакта + лог + pgrep). Поглощено: SKILL.md
(«Пользователь в петле»), codex-exec (фоновый запуск, раннер).
- Безадресный resume подхватывает чужой тред. Поглощено: codex-exec.
- Доводы отклонений — в файл задачи (свежий тред продолжает без контекста
предшественника). Поглощено: prompts/triage-header.md.
- Не поглощено (держать в уме при постановке): правила задачи ранжировать
явно («правило A главнее буквы E») — внутренние противоречия всплывают
после починки.
- Цифры: реализация 18 мин; триаж ~8 мин; тесты 147 -> 154.
**Слепое двойное ревью — родословные поймали разное:**
- Клод (Опус): APPROVE; подтвердил математику поворота/коридора
(алгебраическое тождество), краевые случаи (ряд через ноль, нули),
неизменность метрик и таблиц; посмотрел картинки из `.ipynb`; один nit.
- Codex (свежий тред): needs-attention; две дыры в тестах — раздел ноутбука
не закреплён в required_snippets, нет регрессионного теста «таблица
отрицательного ряда остаётся со знаком». Оба — про то, что зелёный прогон
не докажет готовность; Клод этих дыр не нашёл.
- Пересечения находок — ноль. Слепота и разность родословных работают.
## 2026-07-09 — local-transcriber, SendTo (первый под Windows; дистиллировано 2026-07-12)
**Точечная починка:** Codex `--fresh` с промптом «добавь только два теста,
продуктовый код не трогай» — чисто, 148 → 150 passed.
- Git Bash-стек работает целиком; классификатор режет companion `--write`,
прямой `codex exec` проходит. Поглощено: codex-exec.
- Свежий взгляд: 2 major (OEM-кодировка `.cmd` на кириллическом профиле,
протухание пути venv) + load-bearing порядок проверок. Поглощено: этап 2.
- Отписка: вердикт одной строкой, проверка по JSONL подтвердила работу.
Поглощено: SKILL.md этап 4, codex-exec.
- Эмпирический ревьюер (воспроизведение краевых случаев вне репо) — вердикт
твёрже. Поглощено: SKILL.md этап 4, boilerplate шаблонов.
- Цифры: ревью постановки ~57k, кода ~48k, перепроверка ~45k токенов.
**Цифры для калибровки:** ревью Клода на Фабуле (этап постановки) — ~60k
токенов; конвейер целиком — ~3 часа настенного времени, из них реализация
~20 минут; остальное — ревью и оркестрация. На мелочь такое не разворачивать.
## 2026-07-10 — четыре записи (дистиллировано 2026-07-12)
**Смерть ревьюера (тот же день, ревью самого скилла по /claude-team-review):**
Опус-ревьюер дважды ушёл в idle без доставленного отчёта (одно напоминание
по idle-гарду — снова тишина), пользователь подтвердил: субагент исчез из
интерфейса. Спасти отчёт из транскрипта не удалось — jsonl тиммейтов не
нашлись в каталоге проекта. Урок: отчёт фонового ревьюера — скоропортящийся;
если он критичен, проси ревьюера сначала писать результат в файл
(двухканальный протокол раннера из /adversarial-review), а сообщение слать
как указатель. Ревью скилла не состоялось — отложено до боевого прогона.
- Ревьюер Codex без read-only: мандат промптом надёжен, песочница не режется.
Поглощено: codex-exec (ветка ревьюера).
- Sandbox-инцидент CLI 0.144.1 (bwrap+userns vs AppArmor) и ловушка memfd
(профиль на путь bwrap не цепляется — вешать на бинарь codex). Поглощено:
codex-exec + codex-sandbox-apparmor.md.
- Постановка через `/to-tickets` ложится в конвейер без трения; двойное
слепое ревью постановки окупилось (Клод — механика кода, Codex — уровень
требований; пересечение 2 из ~15). Поглощено: SKILL.md этапы 1–2.
- Ретро расхода контекста (3 цикла): находки проходили через оркестратора
до шести раз; review-промпт дублировался; ~7 пустых ходов на idle-пингах.
Поглощено: SKILL.md (роль оркестратора: индекс, cat, файлы), шаблоны.
## Прогон 2026-07-07: наглядность витрины (боевой, полный конвейер)
## Прогон 2026-07-12: clickstream-demo, задача 20 — флаки runtime-гейта
Задача: витрина понятна финансисту без голоса (5 блоков, 5 файлов). Конвейер
отработал целиком: исследование двумя головами → постановка → свежий взгляд
(1 блокер + 9 находок, в т.ч. повторно поймана ловушка name_ru) → Codex 18 мин
→ два слепых ревью → триаж у исполнителя → две точечные правки → приёмка.
Пересечение находок ревьюеров — снова ~ноль (Клод смотрел артефакты глазами и
принял; Codex дал 4 «поправить» по букве задачи). Их прямое противоречие
(ослаблен ли тест) рассудил исполнитель по контракту — механизм работает.
Полный конвейер + три захода стендовой приёмки. Главный урок прогона:
**ревью по чтению кода не заменяет сквозный прогон** — два класса дефектов
вскрылись только на стенде.
**Ожидание фоновых job:**
- Idle-уведомление субагента ≠ отчёт: почти каждый субагент уходил в idle ДО
доставки отчёта. Лечится немедленным явным «пришли отчёт на main».
- Фоновый bash-поллер (`until…sleep`) у раннера умирает при смене хода.
Надёжно: persistent Monitor без таймаута.
- Статус job — не истина: воркер финальной правки умер после успешных проверок,
статус завис «running» навсегда (зомби). Диагностика оркестратором: mtime
артефакта (showcase-check.ipynb дописан) + лог job (все проверки зелёные) +
pgrep (воркера нет) → забрать финал себе, раннера распустить.
**Что поймал каждый этап:**
- Ревью постановки (Opus): настоящий корень — отсутствие SIGTERM-хендлера
(python PID 1, SIGKILL после grace); один из двух вариантов фикса в
постановке гонку не закрывал. Плюс критерий «красный сценарий всё ещё
ловится» и запрет вероятностных смягчений.
- Слепые ревью: Codex — grace-период 10с и обходимость precheck (пара из
старой backfill-строки); Клод — подтвердил структурный довод, на узкой
перепроверке принёс НОВУЮ находку (тест биндил порт 9109 — флаки 1/13).
Пересечение — 2 темы из ~8 (grace, слабый контракт-тест): не «стабильно
ноль», но малое; обе родословные оправдались.
- Стендовая приёмка (3 захода): (1) гейт годами жил на побочном эффекте
бага — пересекающие визиты давала «нелегальная переработка» генератора
после игнорируемого SIGTERM; честный фикс оставил проверку без сырья;
(2) таймзона: наивные метки STG (UTC) против границы с `+00:00` на
сервере Europe/Moscow — precheck был зелёным вакуумно; та же ошибка — в
приёмочном скрипте координатора (наивная конвенция DDS). Урок: сравнение
времени в SQL — только с явным поясом с обеих сторон.
**Codex companion:**
- Безадресный `--resume`/resumeLast резолвится в «последний тред сессии» — при
параллельных тредах подхватывает чужой read-only ревью-тред. С ЯВНЫМ id тред
подхватывается свой (сэндбокс привязан к треду: у write-треда останется write) —
это же проходили в /adversarial-review. Правило: resume — только по id; если id
не сохранился, свежий write-тред дочитает контекст из файла задачи (решения
вписаны туда).
**Ретро контекста оркестратора** (главный пожиратель — внеплановые циклы):
диагнозы падений приёмки велись мастером инлайн (~15 вызовов); boilerplate
промптов переписывался трижды; обменные файлы шли кириллицей (×1,5–2);
правки задачи-файла — тремя крупными Edit (old+new = двойной текст);
промпты будильников пересказывали план. Поглощено 2026-07-12: SKILL.md
(принцип «мастер решает — субагенты выясняют», стоп-кран «сам — максимум
один заход», механика — fast-worker'у, обменные файлы на английском,
будильник одной строкой, сквозная проверка до ревью, фолбэк ревьюера
deep-reasoner — обкатан этим прогоном), prompt-templates + prompts/
(готовые boilerplate-файлы, английские скелеты), codex-exec (модель
gpt-5.6-sol, medium для узких починок, ловушка `&`). Слепое Fable-ревью
самого скилла (по глоссарию writing-great-skills): восстановление после
rm -rf подтверждено без потерь, 9 MINOR + 5 NIT согласованности — все
закрыты тем же днём.
**Постановка:**
- Правила задачи стоит ранжировать явно («правило A главнее буквы E»):
внутреннее противоречие (де-жаргон vs «заголовки не трогать») всплыло только
после починки по ревью и потребовало отдельной правки решением оркестратора.
- Требовать от исполнителя вписывать доводы отклонений в файл задачи — окупилось:
свежий write-тред продолжил работу без контекста предшественника.
**Прочее:** казус двойного фона (`&` при run_in_background) — спасён
ожидателем `kill -0`; принятие остаточного риска (публикация не ограничена
по времени) зафиксировано доводом в задаче — паттерн «риск принят + после
фикса такой отказ падает громко и честно» работает как аргумент приёмки.
Отдельный казус координатора: `rm -rf` «зеркала» скилла прошёл сквозь
симлинк `~/.claude/skills -> dotfiles` и снёс оригинал; восстановлено из
git (`git show HEAD:path`) + повторным наложением правок из контекста.
Урок: перед rm — `ls -la` цели и родителя, симлинк-родитель = чужая
территория.
**Цифры:** реализация 18 мин; триаж-починка ~8 мин; финальная правка ~3 мин
работы + ~20 мин зомби-ожидания. Тесты 147 → 154. Панель конвенций дала демо
аргумент: 10 из 13 против 6 из 13 в зависимости от прочтения порога.
## Прогон 2026-07-09: local-transcriber, SendTo-меню (первый по тексту скилла; первый под Windows)
Задача: контекстное меню проводника через SendTo + флаги
`--install-menu`/`--uninstall-menu`; 5 файлов, +345 строк, тесты в финале
191 passed / 1 skipped. Конвейер целиком, вместе с фичей — один вечер.
**Первый прогон под Windows:** Git Bash-стек работает целиком — `codex exec`,
`jq`, редиректы, heredoc, фоновый Bash с побудкой, SendMessage-rerun.
Скретчпад сессии вместо `/tmp`.
**Классификатор авторежима — новый класс препятствия:** companion с
`--write` заблокирован и через раннера-субагента, и напрямую из Bash
(«Create Unsafe Agents»); повторная попытка с другим флагом расценена как
обход. Прямой `codex exec` фоновым Bash оркестратора прошёл гейт и отработал
все три ветки (write-исполнитель, read-only ревьюер, resume-триаж). Правила —
в codex-exec.md; companion-обёртка поглощена им же.
**Свежий взгляд на постановку — снова окупился:** 2 major, которые
исполнитель молча реализовал бы: `.cmd` с путём, писанный «как ASCII», ломался
бы на кириллическом профиле (cmd.exe читает батники в OEM-кодировке) — при
том что фича делалась именно «для коллег»; плюс протухание зашитого пути к
venv. Третья находка — load-bearing порядок проверок (exit 2 требует
валидации до `expand_globs`, иначе чужой except даст exit 1). Одна находка
отклонена письменно (проброс `%errorlevel%` — нет потребителя).
**Слепое двойное ревью:** Codex — APPROVED, 0 находок; Опус — APPROVED,
3 minor (0-байтный leftover при `UnicodeEncodeError` — воспроизвёл на
машине; OEM-запись ни разу не исполняется в тестах; LF vs CRLF). Пересечение
снова ~ноль, но с нюансом: Codex в промежуточных сообщениях *колебался*
ровно над местом находки №2 Опуса и не оформил её — колебания в логе стоят
чтения при синтезе.
**Отписка:** вердикт Codex пришёл одной строкой без находок. Проверка по
JSONL (19 command_execution: полный pytest, узкий прогон, usage) подтвердила
работу. Приём «вердикт без находок — проверь лог» вписан в SKILL.md
(этап 4) и codex-exec.md.
**Закрыты давние пункты «не проверено боем» (записка 2026-07-06, ныне
поглощена):** фолбэк-ревьюер
general-purpose на Опусе — обкатан дважды (постановка и код), работает;
триаж исполнителем — `codex exec resume` по явному id закрыл 3/3 находки,
лишнего не тронул; узкий rerun ревьюера — SendMessage поднял того же
Опус-агента из транскрипта, RECHECK OK за ~38 сек.
**Эмпирический ревьюер:** Опус сам воспроизводил краевые случаи вне репо
(UnicodeEncodeError с обрезкой файла, LF-`.cmd` через `cmd /c`) — вердикт
заметно твёрже. Приём поощрять в промпте ревьюера («безопасные
эмпирические проверки вне репо разрешены»).
**Цифры:** ревью постановки ~57k токенов, ревью кода ~48k, перепроверка
~45k (тот же агент из транскрипта); триаж-раунд Codex — одна resume-команда.
## 2026-07-10 — правка по практике пользователя: Codex-ревьюер без read-only
Ветка «ревьюер» в codex-exec.md была записана как `-s read-only` — по
осторожности, не по эмпирике. Пользователь поправил: read-only-конфайн
обедняет ревью — с записью и авто-аппрувом ревьюер гоняет тесты, проверяет
гипотезы, гуглит, читает документацию и первоисточники. Инструкцию
«исходники/окружение не менять» Codex держит надёжно (многократная практика
пользователя). Итог: обе ветки (исполнитель и ревьюер) ходят одним вызовом,
различие — мандат промптом; подстраховка — сверка `git status --porcelain`
до/после ревью. Непроверенное — в handoff 2026-07-10 (сеть под
workspace-write-песочницей для поиска).
## 2026-07-10 — Linux: sandbox-инцидент Codex CLI 0.144.1 (другая сессия, Ubuntu 24.04)
Обновление npm-пакета codex молча сломало песочницу: backend сменился на
bwrap+userns, AppArmor Ubuntu 24.04 блокирует его до запуска команд.
Характерная сигнатура: «гуглит, но не может выполнить `ls`» (web_search
исполняется вне sandbox). Обход без sudo — `use_legacy_landlock=true`
(только read-only, write паникует); полный фикс — AppArmor-профиль
`codex-bwrap` (на той машине не применён, write ждёт sudo). При странных
отказах Codex первым делом — `codex --version` и дата обновления.
Подробности — references/codex-sandbox-fix-handover-2026-07-10.md
(принесено из ветки `codex-sandbox-fix-20260710`).
## Прогон 2026-07-10: mws-data-test-t2-presale, постановка FTP/CSV DQ (этапы 1–2 без реализации)
Постановка велась не файлом-задачей, а `/to-tickets` (репозиторий настроен
`/setup-matt-pocock-skills`): 5 тикетов-срезов с рёбрами блокировок; связка
с конвейером легла без трения — тикет и есть файл-задача этапа 1. Урок
поглощён SKILL.md (этап 1).
**Двойное слепое ревью постановки — впервые, окупилось:** Клод (Опус,
9 находок) поймал механику кода — нереализуемый контракт «таблица под именем
из `table`» (поле недоступно коннектору в момент создания соединения),
мёртвый стаб-ловушку `dataframe`, `load_config` = API-эндпоинт, а не CLI.
Codex (8 находок) поймал уровень требований: параметр из спеки, пропавший в
тикетах; критерий, который можно закрыть формально; поведение при
неподдерживаемом FTP `SIZE`; ненаблюдаемость «понятных ошибок» за общим
`SourceQueryException`. Пересечение — 2 темы из ~15 (Django-противоречие в
тестах, несамодостаточность smoke). Рамка мандата Codex обязательна:
«ревьюируй постановку, не реализацию» — наблюдение пользователя: без неё
зарывается в детали. Урок поглощён SKILL.md (этап 2).
**Ретро-оговорка:** Codex-ревью этого прогона шло ещё через companion-канал
(обновление скилла с прямым exec приехало позже) — с учётом issue #158
чистота родословной второй линии не гарантирована; находки от этого не
обесценились, но эмпирику «2 из 15» читать с этой поправкой.
**Наблюдение пользователя (в память проекта тоже записано):** Codex хорошо
ревьюит планы/постановки, не только код — при явной рамке уровня.
## Прогон 2026-07-10 (позже): AppArmor-фикс — ловушка memfd
Рецепт «профиль на путь vendored bwrap» из handover-файла оказался
недостаточным: Codex ≥0.144 исполняет встроенный bwrap **из memfd**
(`bundled_bwrap.rs`, `memfd_create` в бинаре) — путевой attachment не
цепляется никогда. Коварство: прямой запуск vendored bwrap с диска под
профилем проходит (BWRAP_OK) — ложное подтверждение фикса; истина — в audit:
`profile="unconfined" comm="bwrap"` → transition. Рабочий фикс — профиль на
**сам бинарь codex**: метка наследуется через memfd-exec, `userns,`
срабатывает у ребёнка (стандартный приём Ubuntu для браузеров). Применён и
проверен: оба режима работают, изоляция цела. Обновлённый рецепт — в
handover-файле.
## Ретро 2026-07-10: расход контекста оркестратора за 3 цикла (тикеты 01–03)
Конвейер отработал (3 цикла: реализация → двойное слепое ревью → триаж →
узкие перепроверки → коммит; пересечение находок ревьюеров — ноль во всех
трёх, подтверждая ценность двух родословных). Главные пожиратели контекста
оркестратора, по убыванию:
1. **Находки ревью проходили через оркестратора до шести раз**: вердикт →
Write fix-промпта с находками «дословно» → пересказ резолюций в двух
recheck-промптах → SendMessage-эхо (tool result возвращает весь текст
сообщения). Лечение — «индекс у оркестратора, нагрузка файлами»:
вердикты в файлы, fix-промпт cat'ом, recheck ссылкой на файл отчёта.
Внесено в SKILL.md (роль оркестратора, этапы 4–5) и codex-exec.md.
2. **Review-промпт уходил полным текстом дважды** (файл для Codex +
параметр prompt Клод-субагента, ~80 строк × 2 × 3 тикета). Лечение —
один канонический файл, оба читают сами; скелеты — prompt-templates.md.
3. **Idle-пинги teammate-ревьюера**: ~7 пустых ходов; вердикт не приходит
сам — нужен запрос. Лечение — мандат «финальный акт — SendMessage с
коротким вердиктом», idle-пинги игнорировать.
4. Сага починки санбокса — разовая, задокументирована отдельно.
Обменный каталог прогона — временный, с полуслучайным префиксом (скретчпад
сессии или mktemp -d): не мусорит в репо и не переживает ребут (решение
пользователя).
**Цифры:** реализация ~25 мин; ревью постановки 75k токенов субагента,
ревью кода 65k, перепроверка 80k (с новой находкой); приёмка — 4 прогона
гейта по ~1,5 мин + красный сценарий; тесты 190 -> 192 + 21.