claude-harness/docs/retro/2026-10-11.md
andrey.epifantsev 897fa0f3a7 feat: install.sh ставит allow-правила цикла фичи, --no-permissions для отказа (#24, 0.5.0)
Пересмотр решения владельца 2: allow-правила (git worktree, git branch
-m/-D, push фичевых и chore-веток, push --delete, tea issues/pulls
create/list/edit/comments) ставит install.sh в ~/.claude/settings.json,
а не владелец руками. Список — global/permissions.json; merge и push в
main в нём нет. Правила только дописываются, чужие не трогаются; копия
списка — ~/.claude/harness/permissions.json для doctor.sh.

- install.sh: шаг 5 — слияние permissions.allow; --no-permissions;
  неизвестный аргумент — ошибка; --check показывает permissions N/M.
- doctor.sh, «Машина»: ok / WARN со списком недостающих / MISS.
- adopt/new-project: строка push --delete — для --no-permissions.
- harness-doctor: агент чинит install.sh --no-permissions, права ставит
  владелец (иначе обход отказа классификатора auto mode).
- EnterWorktree не входит: вход в worktree вне .claude/worktrees/
  спрашивает подтверждение при любых правилах (#25).
- README, HARNESS.md, roles/dev.md, CLAUDE.md, ретро (пометка о
  пересмотре решения 2), CHANGELOG 0.5.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 00:01:57 +04:00

24 KiB
Raw Blame History

Ретроспектива обвязки claude-harness — 11.10.2026

Период: 02.10–11.10.2026, полигон — workspace awp-ca (АРМ КА: пять git-репозиториев рядом, workspace сам не git). Предыдущая точка сравнения — PILOT-2026-09-27.md (один репозиторий, одна фича).

Источники: 47 транскриптов сессий Claude Code (~/.claude/projects/-Users-andrey-epifancev-projects-awp-ca/*.jsonl, 841 МБ), 47 файлов auto-memory того же проекта (179 КБ), код хуков, HARNESS.md, PILOT-2026-09-27.md, CHANGELOG.md. Количественная часть считалась скриптами scripts/retro_stats.py и scripts/retro_blocks.py (только чтение транскриптов). Качественная часть — прочтение всей памяти целиком.

Маркировка находок ретро: RT-n. Приоритет: P1 — теряет время каждую неделю или ломает процесс; P2 — трение; P3 — наблюдение. Статус находки проставляется при закрытии бэклога (fixed / deferred / rejected), как и для любых других маркеров обвязки.

1. Цифры

Показатель Значение
Сессий (непустых) 44 за 10 дней; 3 сессии больше 20 МБ транскрипта
Промптов владельца 613
Ходов модели / вызовов инструментов 12 121 / 6 583 (Bash 4 302, Playwright ≈1 100, Read 346, Write 271, Edit 233)
Запусков сабагентов 61 (sonnet 47, opus 9, модель не указана 5)
Вызовов skills brainstorming 19, writing-plans 14, systematic-debugging 8, SDD 4, executing-plans 3, using-git-worktrees 3, TDD 1, finishing-a-development-branch 1, verification-before-completion 0, requesting/receiving-code-review 0
Токены вывод 18,3 М; чтение из кэша 3,82 Г; запись в кэш 145 М
Компакций контекста 4 (в двух сессиях)
Стартовый контекст до первого промпта медиана 56 К токенов (мин 52 К, макс 61 К); наши инструкции ≈39 КБ текста ≈ 13–16 К токенов, остальное — системный промпт и схемы инструментов
Блокировок хуков 103 (guard-main Bash 91, guard-main Edit/Write 8, require-plan 3, прочие 1)
Отказов классификатора auto mode 6 (Git Destructive 2, Auto-Mode Bypass 2, Interfere With Workloads 1, safety-check 1); отказов владельца — 6
codegraph init в командах / вызовов codegraph_explore 43 / 15
cd в основной checkout на main (не .wt/) 84
Промптов «перечитай память/контекст» 9 из 613

Сессии по ролям (эвристика по инструментам и первым промптам): разработка — 32 сессии, 377 промптов; администрирование (Jira, Гант, спринт) — 7 сессий, 122 промпта, все за 10–11.10; QA/фронт (Playwright > 30 вызовов) — 5 сессий, 81 промпт. Администрирование и QA — треть промптов, при этом вся обвязка и 44 из 47 файлов памяти написаны под разработчика.

2. Находки

Хуки

RT-1 (P1). Три четверти блокировок guard-main — ложные. Из 91 блокировки Bash: 36 — команда только чтения с 2>/dev/null (регулярное выражение хука считает N> записью); 27 — команда без единого паттерна записи в репозиторий (чтение памяти, grep, cat), заблокирована потому, что cwd оболочки стоял на main-checkout; 8 блокировок Edit/Write пришлись на файлы вне любого репозитория (scratchpad сессии, файлы памяти) — хук смотрит на cwd, а не на путь файла. Ещё около 20 — шаги самого процесса, которые хук не узнал: git -C <repo> worktree add (исключение есть только для литерала git worktree), mkdir -p .wt/<задача> в не-git workspace, архивный git add openspec && git commit (проверка staged идёт до add). Реальных перехватов записи в main за 10 дней — единицы (sed -i по docs на main в сессии d60ad490). Нарушений main при этом не было ни одного: хук защищает, но ценой шума. Корень: решение принимается по cwd оболочки, а не по цели записи. То же даёт RT-2. Источники: retro_blocks.py, память workspace-hooks-and-worktrees, q1-2025-run, osv-inn-mapping-rework, console-files-state.

RT-2 (P1). Общий cwd оболочки с фоновым SDD-контроллером. Один cd в основной checkout из главной сессии переводит контроллер и всех его implementer-ов в состояние BLOCKED: shell write on main, и они останавливаются. Правило «не cd, пока контроллер работает» записано в шести файлах памяти, то есть повторяется, а не устранено. Устраняется вместе с RT-1: хук, не зависящий от cwd, не ломается от чужого cd. Источники: память slice-2a/2c/3a/3b-state, auto-confirm-64, arm-web-demo-prototype.

RT-3 (P1). Пункт 4 чеклиста закрытия (удалить ветку на сервере) стабильно не выполняется. git push origin --delete блокируется guard-main при cwd на main и отклоняется классификатором auto mode как Git Destructive / Auto-Mode Bypass (4 из 6 отказов классификатора за период). Висящие серверные ветки упомянуты в 10 файлах памяти; владелец удаляет их руками. Найденный опытным путём обход (push из worktree на не-main ветке) нигде в обвязке не описан. Один раз агент обошёл хук через Gitea API, за что получил замечание (feedback-no-harness-bypass).

RT-4 (P1). Правило «архив OpenSpec прямо в main» не работает в многорепозиторном workspace. Глобальный guard-main пропускает openspec-only коммиты, workspace-хук awp-ca запрещает любой commit/push в main без исключений. Итог: около 15 отдельных архивных PR, а поведение «то проходит, то нет» описано в памяти как урок. CLAUDE.md и фактическая практика расходятся.

RT-5 (P2). Workspace-хук срабатывает на слово commit/push в любом месте команды, включая echo, и на reference-old-arm в командах удаления симлинков при сносе worktree (владелец удаляет симлинки сам: slice-3a-state, hotfolder-direct-write-state, core-33-golden-tests).

RT-6 (P2). У хуков нет регрессионных тестов. doctor.sh делает самотест на нескольких случаях, но ни один из 103 реальных инцидентов не стал тестом. Транскрипты содержат готовый набор: команда + вердикт хука + факт, была ли это запись в main.

SDD, сабагенты, классификатор

RT-7 (P2). После одного отказа хука классификатор auto mode отклоняет у сабагента последующие коммиты как «Auto-Mode Bypass». Владелец добавил allow-правила git -C .wt/*, git add, git commit вручную. Следствие RT-1: меньше ложных отказов — меньше каскадов.

RT-8 (P2). Поднятый стенд ломает integration/e2e-тесты сабагентов (общая queue group NATS на recognition.result). Повторилось минимум 5 раз, каждый раз оформлено как deferred-находка, системно не починено. Агенту гасить стенд нельзя (Interfere With Workloads), владелец делает через !. Это проектная находка, но обвязка должна давать место для «предусловий окружения перед SDD» (один раз проверить, а не пять раз откладывать).

RT-9 (P3). haiku-implementer подписывает коммиты своим trailer вместо указанного в плане (пилот, R-5/R-7 в console-files-state, O-5 в slice-3a-state); переписать нельзя из-за запрета force-push. Третий повтор одной находки.

RT-10 (P3). Остановленный владельцем контроллер не возобновляется, нужен новый контроллер «на добивку» (slice-3b-state). Ledger при этом работает: возобновление без потерь подтверждено и на пилоте, и в срезах.

RT-11 (P3). Агент один раз спросил режим исполнения вопреки CLAUDE.md (feedback-execution-mode-from-claude-md), и один раз начал задачу «не по харнесу» (сессия e08f3f0b, владелец перезапустил задачу). Процессные правила в 9 КБ глобального CLAUDE.md плюс 16 КБ проектного читаются не всегда; это аргумент за короткие ролевые файлы (RT-14).

codegraph

RT-12 (P2). 43 codegraph init против 15 вызовов codegraph_explore за 10 дней; Bash — 4 302. В памяти нет ни одного свидетельства, что codegraph ускорил задачу; есть только «init сделан» как ритуал на каждый worktree и пустой ответ на пилоте. При этом правило «implementer вызывает codegraph_explore вместо grep/Read» стоит в глобальном CLAUDE.md. Сервер отстаёт по версии (1.6.0 при доступной 1.6.2).

Память и контекст

RT-13 (P1). Auto-memory стала журналом состояния срезов и дублирует Gitea. 30 из 47 файлов имеют статус «ЗАКРЫТ» и фиксируют «issue #N закрыта, PR #M слит, ветка удалена» — то, что по замыслу обвязки помнит Gitea. Факты внутри файлов расходятся с индексом (slice-4-state: в индексе «ЗАКРЫТ», в файле «ждут мержа»; logger-diagnose-state: ветки «не удалены» в тексте, «удалены» в индексе). Один файл (jira-backlog-actualization, 15 КБ) — журнал версий артефакта v27…v37. Уникальные знания, ради которых память нужна, занимают малую долю: уроки по хукам, три файла фидбека владельца, рецепты QA (стенд, Playwright, скриншоты), структура Jira и ловушки REST, решения владельца по OQ.

RT-14 (P1). Одна обвязка на четыре роли. Разработчик, администратор проекта, аналитик требований и QA работают в одном проекте с одним CLAUDE.md, одним индексом памяти и одним процессом. В админ-сессии грузятся инварианты DBML и поток superpowers→Gitea→OpenSpec; в дев-сессии — Jira-память. Специализированных агентов в обвязке нет вовсе (ни ~/.claude/agents, ни .claude/agents), SDD-контроллер описан текстом. Дизайн решения согласован отдельно (skill /role, файлы ролей, агенты с собственной памятью, реорганизация индекса); здесь фиксируется как находка.

RT-15 (P3). Стартовый контекст 56 К токенов, из них наши инструкции 13–16 К. Роли срежут 8–10 К в не-дев сессиях, но главный выигрыш от ролей — не токены, а отсутствие чужих правил. Платформенная часть (≈40 К) не наша.

Процесс и чеклисты

RT-16 (P2). Bounded-путь не требует обновления спек. Bounded-PR arm-core #52/#53 изменили поведение API без правки openspec/specs; понадобился отдельный аудит (#60, четыре PR). Для bounded нужен один пункт: «меняется поведение API/схемы — спека обновляется в том же PR».

RT-17 (P2). Сборка многорепозиторного worktree делается руками каждый раз: симлинки fixtures/CLAUDE.md/.claude/reference-old-arm, .bounded, venv, симлинк node_modules, codegraph init. Ловушки: worktree remove отказывает из-за симлинка node_modules; относительный путь в git worktree add считается от репозитория, не от cwd. Около 25 bounded-задач и 7 срезов — столько же ручных сборок.

RT-18 (P3). Skills завершения не используются: finishing-a-development-branch 1 раз, verification-before-completion и requesting-code-review 0 раз. Закрытие и ревью идут по чеклисту CLAUDE.md и через SDD. Это не обязательно плохо, но значит, что превентивные проверки (verification) для bounded-задач не выполняются формально.

RT-19 (P3). harness-check и adopt-project не оставили следов в awp-ca: workspace не git, хук молчит. Для режима «workspace из нескольких репозиториев» у обвязки нет ни проверки, ни бутстрапа; doctor.sh его тоже не знает.

RT-20 (P3). Follow-up issues растут быстрее, чем закрываются: за период создано около 40 follow-up issue по чеклисту п. 6 (core, tp, sg, docs, web). Механизм работает, но нет ритуала их разбора. Это кандидат на роль администратора.

3. Что сработало (сохранить)

  • guard-main защитил main: за 10 дней ни одного коммита в main мимо PR. Все потери — ложные срабатывания, не пропуски.
  • Ledger SDD переживает обрыв контроллера; возобновление без потерь подтверждено повторно.
  • Маркировка находок и follow-up issue: находки не теряются между сессиями, каждая имеет статус.
  • design.md «Decisions made without discussion»: десятки решений на срез, прослеживаемы после удаления ledger и чата.
  • Финальное ревью ветки на opus реально находит дефекты (I-1…I-4 в #42, волна C-1/I-1/M-1…M-8 в 3b).
  • Golden-тесты как гарант парсеров: 138/138, 113 снимков, порог MIN_SNAPSHOTS.
  • Чеклист закрытия выполняется целиком в большинстве случаев; слабое место — только п. 4 (RT-3).
  • Фидбек владельца, записанный в память (три файла), изменил поведение: сверка с макетом, запрет обхода хуков, режим исполнения.
  • Спека как источник истины при рулингах (F-1 на пилоте, решения №15/№16 в 3a).

4. Бэклог улучшений (по приоритету)

# Что Находки Оценка
B1 guard-main: решать по цели записи, не по cwd. Игнорировать N>/N>&; для Edit/Write брать ветку репозитория файла; для Bash — git -C <dir> или пути в команде; записи вне git-репозиториев не блокировать; исключения для git -C … worktree add, mkdir -p .wt/; архивная проверка по путям в команде RT-1, RT-2, RT-7 1 день + тесты
B2 Регрессионные тесты хуков на реальных командах из транскриптов (103 случая → фикстуры с ожидаемым вердиктом); запуск из doctor.sh RT-6 0,5 дня
B3 Закрытие п. 4: явный рецепт в CLAUDE.md и HARNESS.md (push --delete из worktree на ветке фичи) либо allow-правило в проектных настройках по решению владельца; перестать перекладывать на владельца RT-3 0,5 дня
B4 Политика архива OpenSpec: либо «всегда отдельным PR» (как фактически), либо workspace-хук учится исключению openspec-only. Привести CLAUDE.md к выбранному RT-4 0,5 дня
B5 Роли: skill /role, файлы ролей (общие в обвязке, проектные в .claude/roles/), агенты с собственной памятью (jira-admin, qa-runner, briefing), подсказка роли по session_title RT-14, RT-11, RT-15 2–3 дня
B6 Политика памяти: состояние задачи живёт в Gitea (комментарий к issue при закрытии), в память — только уроки, фидбек, знания роли; при «закрывай» файл задачи сворачивается в строку реестра; индекс по ролям; одноразовая чистка 47 файлов RT-13 1 день + чистка
B7 Скрипт сборки/сноса многорепозиторного worktree (wt-new, wt-rm): симлинки, .bounded, venv, node_modules, (codegraph по флагу); режим «workspace из репозиториев» в doctor.sh и harness-check RT-17, RT-19 1 день
B8 codegraph: вывести из обязательного потока (без init на worktree и без правила «вместо grep»), оставить опциональным; решение владельца, нужны ли замеры RT-12 0,5 дня
B9 Bounded-чеклист: пункт про спеки при изменении API/схемы; verification-before-completion перед PR RT-16, RT-18 0,5 дня
B10 Workspace-хук: искать git … commit/push как команду, а не как слово; reference-old-arm только для rm-целей, не для симлинков RT-5 0,5 дня
B11 SDD: раздел «предусловия окружения» в плане (стенд погашен, порты свободны); trailer коммита проверяется ревьюером задачи RT-8, RT-9 0,5 дня
B12 Регулярное ретро: skill /harness-retro на этих скриптах, метрики: доля ложных блокировок, отказы классификатора, стартовый контекст, невыполненные пункты закрытия, размер памяти; триггер — по команде после среза все 1 день

Порядок, который предлагается: B1+B2 (убирают главный источник трения и каскад RT-7), затем B5+B6 (роли и память — одно изменение, так как индекс памяти перестраивается под роли), затем B3/B4/B10 (мелкие правила), B12, остальное по мере надобности.

5. Решения владельца (11.10.2026)

  1. Архив OpenSpec — всегда отдельным PR. Исключение openspec-only из guard-main и из CLAUDE.md убирается; правило «в main только через PR» становится без исключений. (B4 → переформулирован.)
  2. Удаление серверных веток — allow-правило в настройках проекта. Строку правила владелец добавляет сам; обвязка даёт готовую строку в adopt-project.sh и в отчёте doctor.sh. Чеклист закрытия п. 4 остаётся за агентом. (B3.) Пересмотрено 23.10.2026 (#24): правило вместе с остальными allow-правилами цикла фичи ставит install.sh в ~/.claude/settings.json; отказ — --no-permissions, тогда строку по-прежнему печатают adopt/new-project и doctor.
  3. codegraph — оставить и замерить. Один срез с обязательным codegraph и подсчётом вызовов codegraph_explore против Bash/Read в тех же задачах; решение после замера. Метрика входит в /harness-retro. (B8 → замер, не вывод из потока.)
  4. Память — политика «состояние задачи в Gitea, в память только уроки, фидбек и знания роли» и одноразовая чистка 47 файлов по ролям. Закрытые срезы сворачиваются в реестр (строка на задачу: PR, follow-up); чистка на копии, с бэкапом, дифф показывается до замены. (B6.)
  5. Роли: состав агентов на первом шаге решается в спеке ролей (предложено: jira-admin, qa-runner, briefing; аналитику — файл роли без агента).

6. Что не удалось измерить

  • Время, потерянное на каждую ложную блокировку: транскрипт не содержит длительности исправления, только факт.
  • Польза codegraph: нет ни одного замера «с ним / без него».
  • Доля решений в design.md, которые владелец потом пересмотрел: нужен разбор архивов OpenSpec, не делался.
  • Поведение памяти вне git (slug по cwd) не описано в документации Claude Code; проверено только наблюдением.