ousterhout-quality-program
Що це робить
Використовуйте щоразу, коли код, що пишеться або переглядається, створює або змінює межу — новий модуль, клас, компонент, хелпер, хук, сервіс або обгортку; будь-яке вилучення або централізація спільного коду; будь-який момент «давайте зробимо це повторно використовуваним» — а також під час явного перегляду, рефакторингу або проєктування модуля. Оцінює, чи виправдовує абстракція свої витрати: глибина модуля, чи варто приховувати рішення про дизайн, чи дубльований код захищає спільний інваріант або просто римується, чи стабільний інтерфейс. Запобігає механічному застосуванню SOLID/Clean Code, що породжує багато поверхневих класів. Також визначає тест вартості для читача (код, який легко читати і змінювати людям і агентам) та процедуру рефакторингу існуючої кодової бази до цього стандарту.
Встановлення відкриє цей запис у вашому настільному додатку AgentsRoom. Якщо додаток ще не встановлено, вас перенаправить на сторінку завантаження.
SKILL.md
--- name: ousterhout-quality-program description: Використовуйте щоразу, коли код, що пишеться або переглядається, створює або змінює межу — новий модуль, клас, компонент, хелпер, хук, сервіс або обгортку; будь-яке вилучення або централізація спільного коду; будь-який момент «давайте зробимо це повторно використовуваним» — а також під час явного перегляду, рефакторингу або проєктування модуля. Оцінює, чи виправдовує абстракція свої витрати: глибина модуля, чи варто приховувати рішення про дизайн, чи дубльований код захищає спільний інваріант або просто римується, чи стабільний інтерфейс. Запобігає механічному застосуванню SOLID/Clean Code, що породжує багато поверхневих класів. Також визначає тест вартості для читача (код, який легко читати і змінювати людям і агентам) та процедуру рефакторингу існуючої кодової бази до цього стандарту. --- # Програма якості Ousterhout ## Огляд Завдання модуля — приховати складність за невеликим інтерфейсом. Основна міра — **глибина**: глибокий модуль пропонує простий інтерфейс над значною функціональністю; інтерфейс мілкого модуля майже так само складний, як і його реалізація, тому він нічого не дає. Складність — це те, що ви відчуваєте, коли зміна змушує вас розуміти або торкатися коду, якого ви не очікували — Ousterhout називає два джерела: **залежності** (ви не можете змінити A без зміни B) і **неочевидність** (важлива інформація не є очевидною). Ousterhout сам по собі говорить, як має *відчуватися* хороший модуль. Він найсильніший у поєднанні з кількома іншими поглядами, які показують, де мають бути межі і як безпечно рухатися до них. Цей навик — це той комбінований погляд. ## Де насправді відбуваються помилки в рев’ю Дві помилки, які цей навик існує, щоб виправити — які неодноразово спостерігалися в коді, написаному агентами — стосуються **виправлення**, а не самого вердикту розділяти/не розділяти: 1. **Мілке виправлення.** При наявності шести `as unknown as` кастів, рев’ювер без допомоги централізує їх в один загальний хелпер `castRows<T>()` — охайніше, але неочевидність залишається. Глибоке виправлення — це типізовані мапери рядок→домен з тестами, закріпленими першочергово (застосовуючи Парнаса: каст — це запах відсутньої межі; Бека: доведіть мапування перед тим, як його переміщувати). Охайне усунення запаху — це не його видалення. 2. **Рефлексивне вилучення.** При наявності однакової логіки оновлення, повтореної в трьох сусідніх компонентах, кожен рев’ювер без допомоги казав «вилучити спільний хелпер» — рефлекс DRY. Правило цієї програми, що розширює Метца: чекайте інваріанта, а не третього схожого випадку — централізуйте, коли код захищає спільне правило, а не коли він римується. Коли ви рекомендуєте виправлення, пропустіть його через обидва: чи усуває воно неочевидність, чи просто її переміщує, і чи вилучення захищає інваріант, чи просто дублює форму? ## Ворота пропорційності Пропускайте цей погляд, коли зміна не додає нової експортованої/імпортованої назви, не створює нового модуля/класу/компонента/хелпера/хуку/сервісу/обгортки і нічого не централізує. Чисті перейменування, механічні кодмоди, редагування конфігурації/даних і одно-рядкові виправлення виключені. У сумнівах запускайте лише два основні тести (глибина, інваріант) і зупиняйтеся. ## Повне правило Кожен шматок згенерованого або переглянутого коду проходить крізь лінзу Ousterhout перед тим, як завдання вважається виконаним — не лише явні дизайн-рев’ю — за винятком змін нижче воріт пропорційності (немає нової межі, немає централізації: перейменування, кодмоди, редагування конфігів). Два тести: (1) **Глибина** — новий інтерфейс має приховувати значно більше, ніж відкривати; інтерфейс, що настільки ж складний, як те, що він обгортає, нічого не дає. (2) **Інваріант** — вилучайте спільний код лише тоді, коли він захищає спільне правило, ніколи через те, що три місця римуються; і виправлення має усувати неочевидність, а не переміщувати її (централізація шести кастів в один хелпер — це все ще шість кастів). Коли зміна створює або змінює межу, спочатку знайдіть, як усталений продукт вирішує проблему такої форми і масштабу, і прийміть його конвенції, якщо немає чіткої причини ні (патерн, згаданий із тренінгу — це твердження, а не джерело), потім запускайте наведені нижче перевірки. ## Коли використовувати - Визначення, чи вартий новий клас/функція/хук свого інтерфейсу, чи це просто мілкий пропуск. - Файл перевищує поріг розміру, і ви вирішуєте *як* його розділити, а не просто чи варто. - Повторюваний код спокушає вас вилучити спільний хелпер. - Проєктування або рев’ю межі навколо бізнес-правила (перевірка області авторизації, правило грошей/округлення, захист переходу станів, правило зберігання даних). - Інтерфейс збирається отримати параметр або спеціальний випадок. - Приведення існуючої кодової бази до цього стандарту — див. розділ «Рефакторинг існуючої кодової бази до цього стандарту» нижче. **Не для:** тривіальних механічних правок або коли структура вже визначена конвенцією проєкту — див. Ворота пропорційності вище. Віддавайте перевагу `karpathy-guidelines` для дисципліни хірургічних змін і навику розробки через тести для безпеки рефакторингу, коли вони доступні. ## Лінзи Кожна лінза додає рівно одне питання. Ousterhout — це основа; інші виправляють його сліпі плями. | Лінза | Одне питання, яке вона додає | Коли вона має пріоритет | |---|---|---| | **Ousterhout** — глибокі модулі | Чи приховує цей інтерфейс більше, ніж він відкриває? | За замовчуванням основа. | | **Parnas** — приховування інформації | Яке рішення в дизайні (ймовірно, що зміниться) приховує цей модуль? | *Причина*, чому модуль має бути глибоким. Якщо він нічого не приховує, що змінюється, глибина косметична. | | **Brooks** — суттєве проти випадкового | Чи усуває це випадкову складність, чи просто переміщує суттєву складність домену? | Вбиває «рефакторинги», які переміщують безлад без його зменшення. | | **Evans** — Domain-Driven Design | Чи названо цю межу мовою домену, а не загальною утилітарною мовою? | Перейменуйте `utils`/`helpers` — назвіть межу за інваріантом, який цей репозиторій справді має. | | **Fowler** — рефакторинг / запахи | Який найменший безпечний крок до глибшого дизайну? | Перетворює «має бути глибше» на конкретні кроки за умови проходження тестів. | | **Beck** — простий дизайн, тестування спочатку | Чи довів я поточну поведінку перед поглибленням шва? | Гальмо проти передчасної архітектури. Спочатку зробіть, щоб працювало і було протестовано, потім поглиблюйте правильний шов. | | **Hickey** — простий проти легкого | Чи переплітає це несумісні концепції, чи це справді одна концепція? | Поверхневий хелпер зазвичай *легкий* (поруч, швидкий), а не *простіший* (мало переплетених концепцій). Віддавайте перевагу простому. | | **Metz** — дублювання краще за неправильну абстракцію | Чи захищає цей повторюваний код спільний інваріант, чи просто схожий (правило цієї програми, що розширює Metz)? | Metz: дублювання дешевше за неправильну абстракцію — замініть неправильну абстракцію на inline, а не гніть її. Ця програма розширює її: **не** централізуйте через повторення; централізуйте лише коли це захищає реальний інваріант. Терпіть дублювання, поки інваріант не виявиться. | | **Закон Гайрума** — спостережувана поведінка | Чи будуть виклики залежати від поведінки поза контрактом цього інтерфейсу? | Аргументує на користь малих, стабільних інтерфейсів: кожна спостережувана поведінка зрештою стає критичною. | ## Рецепт комбінування Застосовуйте в такому порядку — пізніші лінзи мають значення лише після проходження ранніх: 1. **Metz — вхідні ворота.** Чи заслуговує ця межа/абстракція на існування взагалі? Правило цієї програми, що розширює Metz: виділяйте лише тоді, коли код захищає спільне правило — три схожі елементи не є виявленим інваріантом. Якщо ні, зупиніться тут. 2. **Parnas / Ousterhout** — приховайте мінливе рішення (обсяг авторизації, правило округлення, захист переходу, правило збереження) за глибоким модулем. 3. **Evans** — Назвіть цей модуль мовою домену, а не `utils`. 4. **Beck / Fowler** — Для існуючого коду зафіксуйте поточну поведінку тестами, потім рефакторьте до неї маленькими безпечними кроками. Для щойно згенерованого коду поточної поведінки немає — натомість напишіть тест, що визначає бажану поведінку. 5. **Hickey** — Відхиляйте інтерфейси, які змішують несумісні концепції лише тому, що робочі процеси схожі. ## Структурний анти-патерн **Механічний SOLID / Clean Code породжує поверхневі модулі.** Догматичне читання — один клас на відповідальність, виділяти кожну функцію, тримати все маленьким — призводить до рою класів, інтерфейси яких такі ж складні, як і їхні тіла. Коли правило каже «розділіть це», запитайте, яке *рішення* приховує розділення (Parnas) і чи приховує воно більше, ніж відкриває (Ousterhout). Якщо нічого, що змінюється, не приховує, не розділяйте. Цей захист особливо важливий під тиском рефакторингу («почистіть це», «цей файл занадто великий») — у спокійному аналізі рецензенти вже цьому опираються; під час рефакторингу, з мандатом на видимі зміни, пишеться рій поверхневих файлів. ## Поширені помилки - **Розділення лише за розміром.** Модуль запиту на 400 рядків, що приховує одне цілісне рішення, може бути глибшим за чотири модулі по 100 рядків, кожен з яких пропускає ті ж з'єднання. - **Називання розділення `helpers`/`utils`.** Якщо не можете назвати це мовою домену (Evans), межа, ймовірно, неправильна. - **Виділення при другій появі.** Правило цієї програми, що розширює Metz: чекайте інваріанту, а не третього схожого елемента. - **Поглиблення перед фіксацією поведінки.** Beck: без тесту, що доводить поточну поведінку, рефакторинг «поглиблення» — це переписування. - **Вважати проходження модулем.** Обгортка, що передає аргументи, додає інтерфейс і нічого не приховує — за визначенням поверхнева. - **Плутати риму з інваріантом.** Найкращий доказ спільного інваріанту — спільна зміна: копії були виправлені або змінені разом в історії (одна й та сама помилка виправлена в двох місцях). Схожі, що змінюються незалежно, — це рими; залишайте їх дубльованими. - **Очищення запаху замість його усунення.** Централізація шести кастів в один загальний хелпер — це охайна версія тієї ж непрозорості. Глибоке виправлення — назвати межу, яку цей каст приховував. ## Вартість для читача: третій тест Глибина та інваріант визначають, чи має межа існувати. Вартість для читача визначає, чи легко змінювати код навколо неї. Наступний читач, людина або агент, платить за кожен рядок, який потрібно завантажити, щоб безпечно щось змінити. Агенти платять токенами і орієнтуються за текстовим пошуком, частковим читанням і циклами типізації/тестування, тому ті ж дефекти обходяться їм дорожче. Запитайте: - **Знаходиться?** Одна назва на концепцію, однаково написана всюди, доступна через пошук простим текстом. Недоліки: назви, зібрані зі стрічок, зв’язування через побічний ефект імпорту, ланцюги реекспорту, що приховують визначення, дві назви для однієї концепції. - **Чи може читач зупинитися раніше?** Контракт розміщений у верхній частині файлу або над експортом: що він обіцяє, що приховує, чого ніколи не робить. Недолік: контракт можна вивести лише, прочитавши тіло. - **Чи можна перевірити машиною?** Точні типи на вході та виході кожної межі, щоб перевірка типів замінила читання викликачів. Недоліки: `any`, голі словники, булеві прапорці, значення яких живе в тілі. - **Чи видно зв’язність?** Місця, які мають змінюватися разом, забезпечені (спільний тип, тест, єдине джерело) або, якщо ні, позначені на обох сторонах. Ознакою прихованої зв’язності є спільна зміна в історії, про яку нічого не згадується в коді. - **Без шуму?** Немає коментарів, що повторюють код, немає закоментованого коду, немає мертвих гілок, немає коментарів історії змін, немає застарілих шляхів поруч із їх заміною. - **Передбачувано?** Макет відповідає існуючому шаблону репозиторію; тест там, де читач його шукатиме, і запускається самостійно. Розмір файлу навмисно відсутній. Дуже великий файл — це причина шукати друге приховане рішення, ніколи не причина для розрізання: читачі можуть шукати й читати діапазон, а розділення, що нічого не приховує, додає інтерфейси без зменшення навантаження. Для маркерів у коді та карти коду репозиторію використовуйте `context-audit`, де доступно: його якір `AIDEV-NOTE:` (один невідновлюваний факт плюс посилання на походження, максимум два рядки, на місці) — це конвенція для зв’язності, яку не можна забезпечити. ## Рефакторинг існуючої кодової бази до цього стандарту Ретрофіт оцінюється так само, як і новий код; відмінність — у порядку та стриманості. Більшість кодової бази слід залишити без змін. 1. **Перепис, лише для читання.** Перелічіть межі (модулі, сервіси, спільні допоміжні засоби). Для кожного запису: рішення, яке він приховує, або «немає»; розмір інтерфейсу проти тіла; партнери зі спільних змін з історії; дефекти, що ускладнюють читання. Ще нічого не змінюйте. 2. **Ранжуйте за частотою змін, а не за потворністю.** Пріоритет — як часто код змінюється, помножене на вартість його читання. Холодний код, що працює, залишається як є, якою б поверхневою він не був. Важлива складність домену залишається на місці (Брукс). 3. **Призначте по одному рішенню на кожне виявлення:** - прохідний шар або обгортка, що нічого не приховує: видаліть її, викликачі використовують те, що вона обгортала; - неправильна абстракція, викривлена прапорцями та особливими випадками: вбудуйте назад (Метц), потім шукайте справжній інваріант; - поверхневі «брати», що ділять одне рішення: об’єднайте їх за одним інтерфейсом; - витік рішення (викликачі знають формат, правило, схему): опустіть його в модуль, що ним володіє; - загальна назва (`utils`, `helpers`, `manager`): перейменуйте за рішенням, яке вона приховує, або розчиніть у викликачах; - не типізована межа: типізуйте її і замініть касти на мапер, який вони приховували; - прихована зв’язність: забезпечте її або позначте на обох сторонах; - шум: видаліть. Рими, що змінюються незалежно, не отримують рішення. 4. **Спочатку зафіксуйте поведінку.** Жодне рішення не починається, доки тест не доведе поточну поведінку коду, до якого воно торкається (Бек). Рефактори зберігають поведінку; зміна поведінки — окремий коміт. 5. **Розбийте роботу на одиниці, які може виконати один агент.** Одна межа на одиницю. Кожна одиниця називає файли, які вона володіє, контракт, який має зберегти, і команду, що доводить це самостійно. Жодні дві одночасні одиниці не пишуть один і той самий файл; спільні файли (барелі, реєстри, таблиці маршрутів) мають одного власника або чекають інтеграції. Зміни інтерфейсу, від яких залежать кілька одиниць, спочатку впроваджуються як окрема одиниця. 6. **Виміряйте результат.** Виберіть репрезентативну зміну перед початком і порахуйте файли та рядки, які читач має завантажити, щоб її зробити; порахуйте знову після. Експортовані назви та загальна кількість рядків мають зменшуватися або залишатися на місці. Рефактор, що додає інтерфейси, повинен мати заявлену причину. 7. **Зупиніться,** коли те, що залишилось, холодне, суттєве або рима. Пов’язані навички, де доступні: `repo-review` (тип дизайну) створює перепис як артефакт лише для поради; `design-cleanup` запускає цикл виправлення та повторного сканування випадкової складності; `context-audit` додає якорі та карту коду; `ousterhout-build-deep` — це чеклист часу автора для агентів, що виконують одиниці. ## Де це розташовано Ця навичка — це шар огляду та оцінки: використовуйте її, щоб вирішити, чи є абстракція глибокою, названа за правильним рішенням і варта виділення. `find-shared-code` використовує її як тест на прийом, коли переглядає недавню історію на предмет коду, вартий спільного використання. Додаток нижче дає аргументацію кожного автора. --- ## Додаток: Лінзи докладно Режим відмови, який ловить кожен автор, і один крок, який він вам дає. Таблиця вище — це швидкий довідник; це — логіка за нею. ### Оустерхоут — Глибокі модулі (хребет) *Філософія дизайну програмного забезпечення.* - **Глибина** = користь (прихована функціональність) ÷ вартість (складність інтерфейсу). Глибокий модуль приховує багато за малою кількістю. Поверхневий модуль має інтерфейс майже такої ж складності, як і його тіло, тому нічого не заробляє. - **Складність** — це все, що ускладнює розуміння або модифікацію системи. Два джерела: - **Залежності** — не можна змінити одну частину, не торкнувшись іншої. - **Незрозумілість** — важлива інформація неочевидна з коду. - **Симптоми:** посилення змін (одне рішення — багато правок), когнітивне навантаження (скільки треба тримати в голові), невідомі невідомі (не можна сказати, який код зміниться). - **Ключовий крок:** тягнути складність *вниз* — модуль поглинає складний випадок, щоб викликачам не доводилося. Параметри конфігурації та прохідні шари штовхають складність *вгору* до викликачів; це поверхневість. Ловить: інтерфейси, що протікають реалізацію; помічники, що не допомагають. ### Парнас — Приховування інформації (чому глибина важлива) *Про критерії, які слід використовувати при розбитті систем на модулі (1972).* - Розбивайте навколо **рішень у дизайні, які, ймовірно, зміняться**, а не навколо кроків обчислення. Кожен модуль приховує таке рішення. - Це прямий попередник deep module. Модуль є deep *тому, що* він приховує рішення, яке інакше поширювалося б на виклики. Підводні камені: "модуль", який нічого нестабільного не приховує — його глибина косметична. Запитайте: що змінюється за цим інтерфейсом, чого виклики ніколи не бачать? Якщо відповідь "нічого", межа — це прикраса. ### Brooks — Важлива проти випадкової складності *Немає срібної кулі.* - **Важлива** складність притаманна домену (оцінка справді така складна). **Випадкова** складність — це те, що накладають наші інструменти та структура. - Лише випадкову складність можна усунути. Рефакторинг, який "очищує" шляхом перенесення важливої доменної складності з одного файлу в інший, нічого не зробив. Підводні камені: перестановки, замасковані під спрощення. Запитайте: чи знизилася загальна складність, чи вона просто перемістилася? ### Evans — Domain-Driven Design *Domain-Driven Design.* - Межі мають називатися **повсюдною мовою** домену, а не загальними утилітарними термінами. Модуль з назвою `helpers` нічого не називає; модуль `AccessScope` або `PricingPolicy` називає інваріант. - Обмежені контексти не дають бізнес-інваріантам просочуватися через шви. Підводні камені: правильний розподіл з беззмістовними назвами. Якщо ви не можете назвати модуль мовою домену, ймовірно, межу проведено не там. ### Fowler — Рефакторинг і Code Smells *Refactoring.* - Дає конкретні, безпечні, іменовані кроки (Extract Function, Move Field, Replace Conditional with Polymorphism), щоб перейти від поточного дизайну до глибшого. - Кожен крок зберігає поведінку і є малим, тому залишається оборотним. Підводні камені: розрив між "це має бути глибше" і знанням наступного коміту. Ousterhout задає ціль; Fowler — шлях. ### Beck — Простий дизайн, Test-First *Test-Driven Development; XP.* - Чотири правила простого дизайну за порядком, опублікованим Беком: проходить тести, без дублювання, виявляє намір, найменша кількість елементів. Ця програма слідує пізнішому переставленню Fowler/Haines — намір перед дублюванням — бо це служить розширенню правила інваріанту Метца (див. нижче): не дійте на дублювання, доки не зможете назвати намір, який воно захищає. - Test-first — це гальмо проти передчасної архітектури. Спочатку зробіть, щоб працювало, і доведіть поведінку, потім поглиблюйте шов, який тепер захищають тести. Підводні камені: архітектура, побудована до того, як поведінка зафіксована. Без тесту, що доводить поточну поведінку, "поглиблюючий" рефакторинг — це неперевірене переписування. ### Hickey — Простий проти Легкого *Simple Made Easy.* - **Простий** = не заплутаний: одна концепція, не переплетена з іншими (об'єктивно). - **Легкий** = під рукою, знайомий, швидко доступний (відносно вас). - Ці два поняття незалежні. Мілкий хелпер зазвичай *легкий* — швидко написати, поруч — але не *простий*, якщо він переплітає несумісні питання. Підводні камені: зручність, що маскується під дизайн. Віддавайте перевагу конструкціям, які зберігають концепції розділеними, навіть якщо переплетена швидше набирається. ### Metz — Віддавайте перевагу дублюванню, аніж неправильній абстракції *"The Wrong Abstraction" (2016).* - Дублювання набагато дешевше за неправильну абстракцію. Абстракція, витягнута занадто рано, змушує кожного майбутнього виклику підлаштовуватися під припущення, які ніколи не були правдивими для всіх. - Коли абстракція виявляється неправильною, засіб Метца — вбудувати її назад і дозволити дублюванню повернутися, а не підганяти під випадок, для якого вона не була створена. - **Правило цієї програми, що розширює Метца: не централізуйте через повторення коду. Централізуйте, коли це захищає справжній, спільний інваріант.** Поки інваріант не виявиться, терпіть дублювання. Підводні камені: надмірна централізація — мілкий спільний хелпер, навколо якого тепер усі мусять працювати. Це противага механічному "DRY будь-якою ціною". ### Закон Гайрума — Спостережувана поведінка стає контрактом *"З достатньою кількістю користувачів кожна спостережувана поведінка вашої системи буде кимось використана."* - Що б інтерфейс *не робив* — порядок, час, текст помилки — хтось рано чи пізно на це покладеться. Тож поверхня, яку ви відкриваєте, більша за задокументовану. - Це підтримує перевагу Ousterhout за **малими, стабільними інтерфейсами**: чим менше ви відкриваєте, тим менше випадково стає опорною. Підводні камені: широкі інтерфейси, що окам'яніють. Кожен зайвий спостережуваний елемент — майбутнє обмеження. ### Як вони поєднуються - **Parnas → Ousterhout:** приховати нестабільне рішення → модуль глибокий. - **Brooks:** підтвердити, що глибина зняла складність, а не перемістила її. - **Evans:** назвати межу мовою домену. - **Beck → Fowler:** зафіксувати поведінку, потім рефакторити малими безпечними кроками. - **Metz:** не централізувати, поки інваріант не справжній. - **Hickey:** тримати інтерфейс однією концепцією. - **Hyrum:** тримати інтерфейс малим, щоб він залишався стабільним. Небезпека — змішувати Ousterhout з механічним прочитанням SOLID або Clean Code: це породжує багато крихітних класів і функцій з мілкими інтерфейсами — прямо протилежне deep modules. Ousterhout, з Метцом як противагою, — це протиотрута.
Теги
Корисні матеріали
Claude Ads: навичка Claude Code, що перевіряє ваші рекламні акаунти
Claude Ads : це навичка з відкритим кодом для Claude Code: понад 250 перевірок на Google, Meta, LinkedIn, TikTok або Amazon Ads, оцінка зі 100 балів і пріоритетний план дій, приблизно за десять хвилин. Встановлення, команди, обмеження та як оркеструвати це в AgentsRoom.
AGENTS.md: Один файл контексту для кожного агента кодування (Codex, Antigravity, Claude)
AGENTS.md - це портативний файл інструкцій, який ваші AI агенти кодування читають перед тим, як торкнутися вашого коду. Що в нього включити, чим він відрізняється від CLAUDE.md та як зберегти один контекст для Codex, Antigravity і Claude.
Завантажити AgentsRoom
Запускайте всіх своїх AI-агентів на всіх своїх проєктах з одного вікна.
Додаток-компаньйон: контролюйте своїх агентів на ходу
Використовуйте свого: Claude, Codex, Antigravity CLI або іншого AI-провайдера.
Надсилайте баги та запити прямо у свій публічний беклог.