Дев'ять ролей, шість етапів
Роль — це Markdown-файл з коротким frontmatter і промптом. У harness-demo їх дев'ять. Роль — не колонка на дошці: координатор кожного етапу викликає одну чи кілька ролей усередині свого юніта.
| Етап (юніт) | Координатор викликає |
|---|---|
| spec | writer |
| plan | explorer, потім planner |
| prototype | designer |
| implement | tester і implementer; після повернення спершу debugger |
| qa | qa |
| judge | judge |
З увімкненим deliver.pr підтверджена задача отримує ще один крок, і жодна роль його не виконує: runner сам пушить
гілку і відкриває pull request. Його описано на сторінці Життя задачі.
Ролі
Кожна картка каже, що роль читає, що пише і який токен вердикту код від неї чекає.
writer
Перетворює чернетку на два рядки на специфікацію, за якою інша людина могла б це збудувати. Коли чернетка лишає продуктове рішення відкритим, питає тебе, а не вгадує.
- Читає
- твоя чернетка
- Пише
- ## Spec — ціль, user story, обмеження, що поза межами; продуктові питання
explorer
Дешевий і лише читає. Мапить ту частину кодової бази, яку чіпає задача, щоб scope і команди закриття в planner були виміряні, а не
вгадані.
- Читає
- специфікація і код
- Пише
- мапа для planner: файли, місця викликів, наявні тести, тестовий стек
planner
Вирішує, куди йде зміна, і пише контракти для збірки: які файли можна міняти (scope), яка команда має пройти (gate) і як доводиться
закриття.
- Читає
- специфікація і мапа explorer
- Пише
- ## Plan — фази, файли на кожну фазу, scope, gate, критерії приймання; питання, що виникли з коду
designer
Працює лише для задач з kind: ui. Будує клікабельний прототип і зупиняється. Із застосунком знімає маршрут у 1440×900, без нього малює
вайрфрейм. Ти приймаєш його або лишаєш коментар — і він іде на ще одне коло.
- Читає
- план ui-задачі
- Пише
- ## Prototype — маршрут-прототип і його картинка: prototype.png із запущеного маршруту, коли є застосунок, інакше prototype.svg
tester
Спершу пише або оновлює тести — тим тест-раннером, у тій структурі й з тими хелперами, які в проєкті вже є. Так кожен критерій [closes]
отримує щось справжнє, що можна запустити.
- Читає
- план і його критерії [closes]
- Пише
- тести у власному стеку проєкту, в межах scope
implementer
Робить рівно те, що каже план, і ніколи не розширює scope. Якщо план хибний, пише про це у файл задачі, а не тихо лагодить щось інше. Harness комітить тести й код разом після зеленого гейту.
- Читає
- план, його scope і нові тести
- Пише
- код у межах scope, і більше нічого
debugger
Працює лише коли bounces більше нуля. Знаходить причину відмови і передає implementer діагноз, тож наступне коло — це виправлення, а не
сліпа повторна спроба.
- Читає
- звіт qa або судді по поверненій задачі
- Пише
- діагноз для implementer
qa
Запускає кожну команду [closes] і гейт. Із застосунком проходить кожен критерій [found] у браузері й зберігає скриншот на кожен; без
нього перевіряє те, що можуть показати команди й код. Лише читає: ніколи не пише тести і не лагодить код. PASS — коли все виконано, FAIL —
коли перевірений чи пройдений критерій не виконано. «Не можу перевірити» — лише коли команда [closes] або гейт не запускаються, і тоді
задача паркується для людини. Крок, який браузер зробити не може, іде у список для рев'юера.
- Читає
- коміт і критерії приймання
- Пише
- qa-report.md у .harness/artifacts/: рядок на критерій, скриншоти, список For the reviewer
- Вердикт
qa: PASS | FAIL | CANNOT_VERIFY
judge
Налаштований на суперечку і лише читає. Сам перезапускає кожну перевірку закриття і шукає причини, чому робота не готова. Критерії
[found] оцінює за кодом і ніколи не відхиляє задачу лише тому, що їх ніхто не пройшов руками. Браузера суддя не отримує ніколи. Задача
закривається лише з вердиктом судді CONFIRMED.
- Читає
- коміт, план і звіт qa
- Пише
- звіт у .harness/artifacts/
- Вердикт
judge: CONFIRMED | REJECTED
Чому автор тестів — не qa
Здається охайним дати одній ролі і писати тести, і перевіряти роботу. Це пастка.
Тому tester працює всередині implement-юніта, а qa лише читає. Тести й код потрапляють в один коміт, а потім цей коміт перевіряють дві ролі, які не написали з нього нічого. Заодно на коло лишається один юніт, що пише: qa-юніту, який міг би писати, знадобився б власний коміт і ширший контракт scope.
Де закінчується кожна роль
Файл задачі поділено на секції, і в кожної секції один власник. Роль може писати лише у свою секцію. Дашборд пише лише те, чим володіє людина.
| Секція файлу задачі | Хто пише |
|---|---|
## Draft | ти, у дашборді |
## Spec | writer |
## Questions — питання | writer або planner |
## Questions — відповіді | ти, через пікер на картці |
## Plan, ## Acceptance criteria | planner; ти пишеш частину ### Review у ## Plan |
## Prototype | designer; частину ### Review пишеш ти |
title, kind, status при людських переходах | |
status при переходах агентів, ## Log | harness |
Завдяки секціям-власникам два автори ніколи не б'ються за один файл: коли harness і дашборд обидва чіпають задачу, кожен редагує лише свою ділянку. Коду й тестів у файлі задачі немає взагалі; їх стереже контракт scope.
Додай файл — отримай спеціаліста
Дев'ять ролей — стартовий набір, а не закритий список. Harness зливає дві теки в один реєстр:
agents/у harness-demo — базові ролі;<project>/.claude/agents/у твоєму проєкті — твої власні спеціалісти.
Агент проєкту з тим самим ім'ям, що й базовий, заміняє його. Для кожного юніта runner лишає лише агентів, у чиїх
stages: є етап юніта, записує їх у .harness/trace/unit-NNNN.agents.json і передає цей файл у Claude Code через
--agents. У твій проєкт нічого не пишеться. Далі координатор обирає спеціалістів, потрібних задачі.
Новий спеціаліст — це один новий файл. Крім звичних name, description, model і tools, його frontmatter каже, на яких етапах і коли його
можна викликати:
---
name: a11y
description: Checks new UI against keyboard and screen-reader basics
model: sonnet
tools: Read, Grep, Glob
stages: [qa]
when: the task has kind ui
---
Типові спеціалісти проєкту: triager, який розбиває чернетку з кількома задачами всередині, перевірка a11y поруч
із qa для ui-задач і docs, який тримає README і changelog в актуальному стані, в межах scope.
Контракт фіксує лише обов'язкові вердикти для кожного етапу, у config.json проєкту: qa-юніту потрібен токен
qa:, юніту судді — токен judge:. Будь-який додатковий спеціаліст дозволений.
harness agents показує злитий реєстр, harness agents --check проганяє перевірки дрейфу й моделей, а
harness agents --sync копіює постійні правила в кожного базового агента.
Модель на кожну роль
Модель кожного координатора береться з roles.models у config.json. Модель спеціаліста — з його власного
frontmatter, а roles.models.<name> її перевизначає. За замовчуванням implementer і tester працюють на sonnet, суддя —
на opus, explorer — на haiku. За цим вибором стоять два правила:
- Спершу виміряй, потім здешевлюй. Дешевша модель для explorer чи writer може бути ок; дешевший implementer може коштувати більше на повернених колах, ніж зекономить. Міняй одну роль за раз і порівнюй.
- Суддя — навмисно інша модель, ніж implementer і tester. Модель, що рев'юїть вихід свого ж типу, має ті самі сліпі плями. Код здається їй правдоподібним з тих самих причин, з яких вона його написала. Інша модель помиляється по-іншому, тож ловить частину помилок, яких автори не бачать. Це правило примусове: суддя з тією ж моделлю, що й implementer чи tester, змушує runner вийти з кодом 2 — зламана конфігурація.
Якщо два рев'ю-юніти на задачу задорого, увімкни roles.mergeQaJudge: true. Тоді qa-юніт отримує ще й спеціаліста
judge з його критеріями. Qa PASS перезапускає кожну команду [closes], перш ніж задача перейде в done, — так само, як
judge CONFIRMED, — а червоний критерій перетворює PASS на повернення. Колонка Judge зникає. Дешевше і слабше: другого
юніта зі свіжим контекстом більше немає.