Перейти к содержанию

Больше одного агента

Кому это? Тому, у кого над одним репозиторием работают несколько агентов — субагенты в одной сессии, параллельные worktree или headless-прогон рядом с человеком. Когда читать? Когда появляется второй агент. Пока в работе одна полоса, ничего из этого не нужно, и включать заранее незачем. Чтобы сначала разобраться с инструментом — гайд.


Всё остальное, что проверяет этот инструмент, придумано для одного работника за раз. Когда их несколько, ломаются три вещи — и ни одна из них не ломается, пока работник один.

Полоса говорит, что она держит

Полоса объявляет пути, которые она правит, в своём handoff:

## Owns

- src/checkout/
- test/checkout.test.ts

Файл, каталог или префикс с /** — и больше ничего, потому что две заявки должны сравниваться чтением. Шаблон, пересечение которого нельзя вычислить, не защищает ничего, а забор, который молча не держит, хуже, чем его отсутствие.

harnessimo tracks падает, когда две живые полосы заявили пересекающиеся пути, и называет обе полосы и обе заявки:

FAIL  work tracks
  specs/0007-totals/handoff.md:9  src/checkout/totals.ts
    also claimed by specs/0006-checkout as "src/checkout/" (specs/0006-checkout/handoff.md:7)
    — two lanes editing one path is a merge that resolves text and not intent;
      narrow one claim, or finish one lane first

Не объявить ничего — не ошибка. Репозиторию с одной полосой в работе это не нужно; правило существует ради случая, когда один путь заявили двое.

Заявки живут в handoff, а не в спеке и не в индексе, и это выбор: handoff удаляется в тот момент, когда трек закрывается, поэтому заявка не может пережить работу, которую она огораживает.

Две полосы не могут отвечать на один номер

harnessimo track new берёт номер с файловой системы — наибольший на диске плюс один. Два worktree читают одно состояние и оба получают 0006. Каталоги называются по-разному, поэтому git сливает их молча, и в индексе оказываются две полосы под одним номером, который уже попал в сообщения коммитов и в handoff'ы.

Блокировка бы не помогла: блокировка в одном worktree не видна в другом. Чек падает на слитом дереве — там, где коллизия только и существует.

Ход не заканчивается заявлением

harnessimo brief закрывает вход в сессию, pre-commit — вход в коммит. Между этими двумя точками агент может закончить ход словами «готово» при красных проверках, а когда работа уходит не в коммит, а другому агенту, не срабатывает вообще ни один гейт.

harnessimo hooks install --agent

ставит Stop и SubagentStop рядом со стартовым хуком. Красный check не даёт закончить ход и отдаёт отчёт самому агенту — следующее, что он прочитает, это файл, строка и исправление.

SubagentStop важен не меньше Stop: в параллельном прогоне именно субагент заканчивает полосу, и это тот ход, за которым никто не смотрит.

Ход, который уже продолжается из-за этого же хука, повторно не блокируется. Гейт, который нельзя удовлетворить, — это цикл, а цикл — то, как гейт удаляют.

Запускается check — шесть правил, которые занимают около секунды. Холодный старт, переперепроверка и тесты остаются в CI по той же причине, по которой их там оставляет pre-commit: гейт, замедляющий каждый ход, — это гейт, который кто-нибудь снесёт.

Передать одну полосу одному агенту

harnessimo brief --track checkout-totals

Строка этой полосы из индекса, её handoff целиком, что она держит и что держат остальные живые полосы — и ничего из их состояния. brief без ключа — это индекс всего, что в работе: правильный ответ для сессии, которой принадлежит репозиторий, и неправильный для агента, которому выдали одну полосу.

Worktree

claude --worktree даёт каждой сессии свой checkout в .claude/worktrees/ — ровно та форма работы, о которой вся эта страница. Проверки внутри worktree работают так же, как в основном checkout, а основной checkout копию worktree не видит.

И это не везение: каталог, внутри которого лежит свой .git — worktree, сабмодуль, вендоренный клон, — это другой репозиторий, и его файлы не наши. Зайти в него означало бы сканировать каждый документ дважды, а worktree, стоящий на старом коммите, ронял бы проверку на утверждениях, которые здесь уже исправлены.

Гонка за номером полосы выше — это ровно случай worktree: две сессии, два checkout, один и тот же следующий номер.

Чего здесь сознательно нет

Ничего здесь не блокирует, не ждёт и не планирует. Инструмент, которому принадлежит порядок работ, — это инструмент, из которого проект не может выйти, поэтому здесь только объявление и обнаружение: сказать, что две полосы разошлись, а кто уступает — решение человека.

Две вещи описаны и не построены — чтобы честно обозначить, где сейчас граница:

  • Протухшая заявка. Полоса, брошенная на середине, держит свои пути, пока её кто-нибудь не закроет или не поставит на паузу. Чтобы это заметить, нужен возраст, а для возраста — часы, которых у инструмента нет.
  • Объявленные зависимости между полосами. Когда одна полоса строится на интерфейсе другой, проблема в порядке, а не в столкновении, — это другое правило.