Дошка
У harness-demo кожен етап — колонка на канбан-дошці, а status задачі — колонка, в якій вона лежить. Один статус,
одна колонка, один власник. Поки юніт працює над карткою, на ній видно позначку «в роботі».
Колонка = status | Власник | Що там відбувається | Куди далі |
|---|---|---|---|
draft | Пишеш назву і кілька рядків. Submit або перетягування рухає далі. | spec | |
spec | writer | Spec-юніт пише специфікацію. | plan · needs-input |
needs-input | Відповідаєш на відкриті питання на картці. | назад на етап, що питав | |
plan | explorerplanner | Explorer мапить код; planner пише фази, scope, gate і критерії. | planned · needs-input |
planned | Затверджуєш план або повертаєш його planner із коментарем. | prototype для ui-задач, інакше ready; plan з коментарем | |
prototype | designer, потім ти | Designer будує прототип; ти приймаєш або коментуєш. | ready · ще одне коло |
ready | затверджено, чекає | Поки нічого не працює. | implementing, коли стартує implement-юніт |
implementing | testerimplementer | Tester пише тести, implementer — код; harness комітить після зеленого гейту. | qa · parked |
qa | qa | Запускає кожну команду [closes] і гейт; із застосунком проходить кожен критерій [found] у браузері. | judge · implementing · parked |
judge | judge | Перезапускає кожну перевірку закриття і пробує відхилити. | done · implementing |
done | runner | З увімкненим deliver.pr runner пушить гілку і відкриває PR, без агента і без токенів. Без нього done — кінець. | delivered з deliver.pr, інакше нікуди |
delivered | — | Гілку запушено, PR відкрито. | кінець: мерджить людина |
parked | Зупинено з причиною. Reopen повертає назад. | статус, з якого запаркували |
Обери статус, щоб побачити його власника і всі виходи з нього. Перемикачі додають переходи, які існують лише з повною автономією або об'єднаним рев'ю.
- людський перехід (дашборд і CLI пропонують лише такі)
- перехід, який harness робить після юніта, кольором ролі етапу
- park: жорстка зупинка з будь-якого незавершеного статусу
qaqaQa-юніт запускає кожну команду [closes] і гейт і перевіряє критерії, які може. Лише читає.qa-pass→робить harness · без об'єднаного рев'юqa-fail→робить harness · поки bounces + 1 < limits.bouncesqa-fail→робить harness · коли ця відмова досягає limits.bouncespark→parkedпри жорсткій зупинці: scope, файл задачі, trace, gate, помилка агента або таймаут
Хто рухає картку
Є лише два види переходів, і вони ніколи не змішуються.
Ти рухаєш картку, коли потрібне рішення людини: надіслати чернетку, відповісти на питання, затвердити план або повернути його, прийняти чи прокоментувати прототип, перевідкрити запарковану задачу. У дашборді це перетягування або кнопки. Перетягнути можна лише вздовж людського переходу, і дашборд відмовить, поки над задачею працює юніт.
Кожен людський перехід є і командою — для роботи з термінала:
harness new --title "Dark mode toggle" --draft "Users want a dark theme." --kind ui
harness submit T-007 # draft → spec
harness answer T-007 Q1 a # answer an open question, with an optional note
harness approve T-007 # planned → prototype (ui) or ready
harness revise T-007 "split criterion 2 into two checks" # planned → plan, with what the plan should change
harness comment T-007 "move the toggle left of the avatar"
harness accept T-007 # prototype → ready
harness reopen T-007 # parked → the status it was parked from
Додай --project <path>, якщо ти не в теці проєкту.
Harness рухає картку після того, як юніт завершився і його контракти пройшли. Жоден агент не пише status
напряму; це робить runner за результатом юніта.
Інтерв'ю
Агенти питають, а не вгадують. Writer ставить продуктові питання на етапі чернетки; planner — питання, які виникають лише після читання коду. Обидва користуються одним протоколом:
- Агент дописує питання в
## Questionsз двома–чотирма варіантами під літерами, рекомендований — першим. - Ставить
status: needs-inputіresume:зі своїм етапом і завершує юніт зеленим. - Дашборд показує відкриті питання як пікер на картці.
- Твоя відповідь записується під питанням, а питання стає
answered. - Коли відкритих питань немає, harness повертає задачу на етап із
resume.
Writer бачить інші задачі на дошці, тож рекомендований варіант ніколи не дублює роботу іншої задачі; такі задачі специфікація називає у списку «поза scope».
### Q1 · Where should the toggle live? · open
- (a) Header, right of the nav — recommended: visible on every page
- (b) Settings page only
- (c) Both
> **Answer:**
Етап прототипу
Задачі з kind: ui отримують ще один етап перед кодом. Designer будує прототип як маршрут у застосунку і лишає
його картинку в теці артефактів задачі. Із застосунком (проєкт задає app і він стартував) designer відкриває маршрут у браузері й
знімає prototype.png 1440×900, а для інших станів — prototype-2.png і далі. Без нього він малює
prototype.svg: вайрфрейм 1440 px завширшки зі справжнім текстом, розкладкою й кольорами сторінки, кожен стан у
своїй колонці, без накладань. Designer ніколи не запускає й не зупиняє сервер: застосунком володіє runner. Дашборд показує картинку на картці й у шухляді; якщо раунд не лишив картинки, у
## Log з'являється нотатка, і маршрут усе одно можна переглянути. Картка зупиняється в prototype і чекає на тебе:
- Accept переводить задачу в
ready. - Comment повертає її designer на ще одне коло, з твоїм коментарем у
### Review.
Кількість кіл обмежує limits.prototypeRounds, 3 за замовчуванням. Маршрут прототипу прибирається при доставці,
якщо план не каже його лишити.
Скільки автономії
За замовчуванням, з autonomy.mode: gated, harness зупиняється для тебе двічі на задачу: щоб затвердити план і щоб
переглянути прототип.
На гейті плану його можна й повернути. Request changes на вкладці Plan у шухляді або harness revise записує
твій коментар у блок ### Review наприкінці ## Plan, і задача повертається в plan. Наступний раунд плану читає
найновіший коментар і мусить лишити блок без змін. Поки план у planner або поки над задачею працює юніт, повторний запит
відхиляється.
autonomy.mode: full вимикає обидва гейти. Спланована задача рухається далі сама, а готовий прототип іде одразу в
ready. Дві речі й у повному режимі потребують людини: чернетці потрібен Submit, а відкритому питанню — відповідь.
Гілки і доставка
- Коли задача вперше потрапляє в
implementing, harness створює гілкуharness/T-NNN-<slug>від базової гілки проєкту. Це єдина гілка, яку дозволяє контракт scope. - Після кожного implement-юніта із зеленим гейтом harness комітить у цю гілку.
- За замовчуванням доставка — це коміт: з
deliver: { pr: false }задача закінчується вdone. - Перед батчем базова гілка має бути чистою. Supervisor відмовляється працювати на брудному дереві, яке забруднив не він.
Доставка через pull request
Встанови deliver.pr: true у config.json, а також deliver.remote, якщо remote — не origin. Тоді задача в done
отримує ще один крок. Його робить сам runner: без агента і без токенів
(harness/deliver.ts).
- Перевіряє контракт гілки: гілка задачі існує, вона попереду базової гілки, і тема кожного коміту починається з
T-NNN:. - Пише тіло pull request у
.harness/artifacts/T-NNN/pr-body.md: ціль зі специфікації, план, кожен критерій приймання з ✓ і його командою для[closes], з ✓ і скриншотом для[found], який qa пройшов у браузері (решта лишається невідміченою, для людини), рядок про те, скільки таких критеріїв qa пройшов, вердикти qa і judge з номерами юнітів і коміти. - Пушить гілку через
git push -u <remote> <branch>. - Відкриває pull request через
gh pr create. Спершу питаєgh pr view <branch>, тож повтор ніколи не відкриє другий. - Записує
pr: <url>у файл задачі і переводить задачу зdoneуdelivered.
Ніщо ніколи не мерджиться. Harness запускає лише три команди gh: gh auth status, gh pr view і gh pr create;
мердж — за тобою. Якщо падає контракт гілки, пуш чи gh, задачу паркують із причиною (parked: deliver: …), а
Reopen повторює крок.
З увімкненим deliver.pr supervisor перевіряє все до старту: remote, встановлений і залогінений gh, базову гілку на
remote. Якщо чогось бракує, він виходить з кодом 2 і друкує, як це виправити. HARNESS_GH підміняє команду gh так
само, як AGENT_CMD підміняє агента; ним користуються self-тести.
Скільки коштує одна задача
Задача від чернетки до pull request — це п'ять юнітів агентів, кожен зі свіжим контекстом: spec, plan, implement, qa і judge. UI-задача додає раунд прототипу, а інтерв'ю — ще один spec-юніт. Доставка — це крок runner, який не витрачає токенів. Це більше, ніж з'їла б одна довга сесія. Натомість маєш видимість — кожна картка лежить у колонці свого власника — і чистий контекст для кожної ролі.
harness-demo виміряв це на пілоті: чотири справжні задачі на прикладі закладок, claude -p на підписці зі стандартними
моделями, контрольованою автономією і ввімкненою доставкою. Людські гейти проходив Claude, обираючи рекомендовані
варіанти. Усі чотири задачі закінчились відкритим pull request, і нічого не змерджено.
T-005 пройшла вже після того, як qa і designer отримали браузер.
| Задача | Тип | Що сталося | Юніти | Час агентів | Токени | В еквіваленті API | Pull request |
|---|---|---|---|---|---|---|---|
| T-004 Показати, коли додано закладку | logic | план повертали раз; три баги harness паркували задачу дорогою, кожен виправлено | 13 | 6:51 | 25.0k | $2.30 | #2 |
| T-001 Пошук, що фільтрує список | ui | інтерв'ю на 2 питання, прототип прийнято з першого раунду, без повернень | 7 | 3:21 | 11.1k | $1.68 | #3 |
| T-003 Зробити закладки кращими | vague | інтерв'ю на 4 питання, план повертали раз; суддя відхилив перший раунд, другий це виправив | 14 | 7:48 | 18.7k | $2.86 | #4 |
| T-005 Скасування після видалення закладки | ui | інтерв'ю на 1 питання; план повертали раз (він спирався на T-001 і T-004, яких ще не було в main); designer зняв справжній тост; qa пройшов у браузері всі 7 критеріїв [found] | 8 | 6:46 | 17.4k | $2.30 | #5 |
За весь пілот harness stats нарахував 47 юнітів, 5 з них — stand-in агента, і 5 запаркованих: 24:49 часу агентів, 72.1k
токенів і $9.13 в еквіваленті API. Токени — це вхід плюс вихід. Читання з prompt-кешу йдуть зверху і коштують значно
менше. На підписці еквівалент API — це те, скільки ті самі токени коштували б через API, а не рахунок. Кожен збій став
контрактом або рядком промпту з тестом; загальні висновки — на сторінці уроків.