Часть I. Ремесло
Постановка задачи
В первый вечер вы ставили агенту задачи по нашим подсказкам, и они срабатывали. Пришло время разобрать, почему они были устроены именно так, – и научиться собирать такие самому, без подсказок, под любую свою затею.
Начнём с фразы, которую стоит повесить над рабочим местом: агент делает не то, что вы имели в виду. Агент делает то, что вы описали. Между «имел в виду» и «описал» всегда есть зазор, и всё, что в этот зазор попало, агент заполнит сам – быстро, уверенно и правдоподобно. Форма из первого вечера, выбрасывавшая обращения, родилась ровно в таком зазоре: про сохранение в задаче не было ни слова, и агент выбрал самый дешёвый вариант.
Отсюда определение ремесла, которому посвящена эта часть. Постановка задачи – это работа по сужению зазора. Не поиск волшебных слов, не вежливость и не длина: техника. У неё есть анатомия, и её можно освоить за одну главу.
Анатомия: от одной строки до рабочей задачи
Возьмём пример из вашего же проекта. У сервиса из части 0 копятся обращения, и листать список стало неудобно. Естественное желание – поиск. Он, кстати, лежит у вас в списке отложенного – и пусть лежит: здесь мы разбираем постановку, строить не обязательно. Естественная формулировка:
Добавь поиск по обращениям.
Поставьте себя на место исполнителя, который получил эту строку и не может переспросить. Искать по каким полям – по имени, по тексту, по всему сразу? Где искать – на странице списка или отдельной страницей? Что показывать, когда ничего не нашлось? А когда строка поиска пуста? Трогать ли существующий список или делать рядом? Каждый из этих вопросов агент решит за вас, не сообщая, что решал. Получите вы сумму чужих догадок, оформленную как готовый результат, – и будете разбираться с ней дольше, чем писали бы задачу.
Теперь соберём задачу по частям, добавляя по одному элементу и глядя, что меняется.
Первое: что нужно, в терминах результата.
Добавь на страницу /spisok поиск по обращениям:
одно поле ввода, поиск по имени и тексту обращения.
Уже лучше: определено, где живёт поиск и по каким полям идёт. Но по-прежнему не сказано, как понять, что готово, – и не сказано, чего не делать.
Второе: граница правки. Вы знаете этот приём с первого вечера, теперь у него есть имя и постоянное место – последней строкой любой задачи:
Меняй только страницу списка. Форму, сохранение и базу не трогай.
Цену этой строки вы уже заплатили в первый вечер, когда ставили её впервые: без неё правка расползается по проекту.
Третье: чем проверять. Самый недооценённый элемент. Опишите проверку – и вы автоматически описали поведение во всех важных случаях:
Проверка: по слову из текста обращения находится нужное;
по пустому полю показывается весь список;
по слову, которого нет нигде, – сообщение «ничего не найдено»
и ссылка на полный список.
Заметьте, что произошло: формулируя проверку, вы приняли три решения о поведении – те самые, которые иначе принял бы агент. Пустое поле, пустой результат, путь назад. Это главный секрет элемента «чем проверять»: он заставляет вас продумать края задачи до того, как код существует. Края – то место, где живут почти все поломки.
Четвёртое: чего не делать.
Не добавляй фильтры, сортировку и постраничную разбивку – не сейчас.
Без запретов агент достраивает «полезное»: раз поиск, то и фильтры, и сортировка, и разбивка по страницам. Каждая добавка увеличивает объём непроверенного. Запрет – это способ получить ровно один проверяемый шаг вместо трёх непроверяемых.
Соберём целиком:
Добавь на страницу /spisok поиск по обращениям:
одно поле ввода, поиск по имени и тексту обращения.
Проверка: по слову из текста находится нужное обращение;
по пустому полю показывается весь список; по слову, которого
нет нигде, – сообщение «ничего не найдено» и ссылка на полный список.
Не добавляй фильтры, сортировку и постраничную разбивку.
Меняй только страницу списка. Форму, сохранение и базу не трогай.
Восемь строк вместо одной. Время на написание – три минуты. Эти три минуты вы окупите в первые же десять: результат либо совпадёт с описанным, либо расхождение будет видно сразу, потому что есть с чем сравнивать. Задача из одной строки не оставляет даже возможности заметить расхождение – сравнивать не с чем.
Четыре элемента стоит запомнить как формулу: что нужно, чем проверять, чего не делать, где граница. Всё остальное в задаче – украшение. Длинные вступления, вежливые обороты и описания настроения на результат не влияют; влияют эти четыре.
План до кода
Для задач побольше – новая страница, изменение хранения, всё, что затрагивает несколько мест, – к формуле добавляется ход, который бережёт больше всего нервов: попросить план до исполнения.
Пока не пиши код. Опиши, что собираешься сделать: какие файлы
изменишь, какие добавишь, как будет храниться и проверяться.
Агент отвечает текстом на полстраницы, и этот текст – самая дешёвая точка контроля во всём цикле. Ошибка, пойманная в плане, стоит одну реплику: «нет, храни в той же базе, отдельный файл не нужен». Та же ошибка, пойманная в готовом коде, стоит разбора, переделки и нового прогона проверок. Непонимание задачи видно в плане целиком – в коде оно размазано по файлам.
У этого хода есть отраслевое имя – разработка от спецификации: сначала согласованное описание, потом исполнение, потом сверка результата с описанием. Существуют инструменты, которые строят вокруг этого весь рабочий цикл. Знать об этом полезно по одной причине: приём придуман не нами и хитростью не является – это нормальный способ работать, к которому индустрия пришла на тех же ожогах.
И парный ход, ещё дешевле, – передать вопросы на сторону агента:
Прежде чем начать, задай мне вопросы, без которых задача
получится слишком общей.
Это работает лучше, чем кажется, по свойству самой модели: она хорошо видит пробелы в чужом тексте, хуже – в собственных планах. Три-четыре вопроса из ответа обычно попадают в те самые края, которые вы не продумали. Отвечать на вопросы легче, чем предугадывать их, – пусть спрашивает.
Антипример: задача-мешок
Для полноты – как выглядит противоположность. Реальный жанр, встречается постоянно:
Сделай нормальный поиск по обращениям, и заодно поправь дизайн списка,
а то он страшный, и ещё уведомления бы прикрутить, чтобы на почту
приходило, и посмотри, почему вчера медленно работало.
Четыре задачи в одной, ни у одной нет ни проверки, ни границы, а «заодно» и «ещё бы» открывают агенту дверь в любую часть проекта. Результат предсказуем: большая правка во многих файлах, где что-то из четырёх сделано, что-то нет, что-то сделано не так, – и непонятно, с какого конца проверять. Слово «заодно» в задаче агенту вообще стоит запретить себе. К нему мы ещё вернёмся в части про изменения работающего проекта, но рождается оно именно здесь, при постановке.
Правило деления простое. Если в задаче есть «и ещё» – это две задачи. Если результат нельзя проверить одним коротким сценарием – задача велика, делите. Маленькие задачи кажутся медленным путём; на дистанции они быстрее, потому что не порождают разборов «что из этого вообще работает».
Библиотека формулировок
Шесть заготовок, которые закрывают большинство ситуаций. Они уже встречались вам по одной – вот все вместе, в том виде, в каком их стоит держать под рукой:
Граница правки. «Меняй только то, что относится к [задаче]. [Перечень] не трогай». Последней строкой каждой задачи.
План до кода. «Пока не пиши код. Опиши, какие файлы изменишь и добавишь, как будет храниться и проверяться». Для всего, что больше одного файла.
Вопросы к задаче. «Прежде чем начать, задай мне вопросы, без которых задача получится слишком общей». Когда сами чувствуете, что описали смутно.
Критерий готовности. «Готово, когда: [проверяемый сценарий]». Заставляет продумать края.
Запрет на переделку. «Не переписывай работающее. Если считаешь, что нужна переделка, – сначала объясни, что и зачем, не делая». Против «улучшений» по собственной инициативе.
Требование показать проверку. «Покажи, как ты проверил, что это работает. Что запускал, что получил». Приучает и агента, и вас, что «сделал» без «проверил» не считается.
Замечание к библиотеке. Ценность этих формулировок не в словах – слова можете менять как угодно. Ценность в том, какие решения они у вас требуют: назвать границу, описать проверку, отделить нужное от попутного. Это решения владельца, и делегировать их некому: агент исполняет, решает тот, кто ставит задачу.
Если вы заказчик. Формула «что нужно, чем проверять, чего не делать, где граница» – это же скелет хорошего задания подрядчику. Если в вашем задании есть только первый элемент, три остальных подрядчик решит за вас – ровно как агент, только дороже и дольше. Особенно окупается «чем проверять»: задание с проверяемым критерием готовности лишает смысла спор «а мы считаем, что готово».
Упражнение. Возьмите последнюю задачу, которую вы давали агенту, – настоящую, из своей переписки. Разберите её по четырём элементам и найдите отсутствующие; в типичной задаче из жизни присутствует один элемент из четырёх. Перепишите по формуле и дайте агенту заново, в свежей сессии. Сравните два результата – это сравнение убеждает лучше любой главы.
Задача поставлена – агент вернул результат. Следующая глава про вторую половину цикла, о которой почти никто не говорит: как читать то, что вернулось, не читая кода целиком, и как отличать отчёт о работе от самой работы.
Как читать то, что вернул агент
Задача поставлена по всем правилам прошлой главы, агент поработал и вернул результат: пачку файлов, правки в существующих и бодрый отчёт о проделанном. Наступает момент, который пугает больше всего: это надо как-то оценить. Кода много, понимаете вы в нём не всё, а нажать «принять» не глядя – значит впустить в проект неизвестно что.
Хорошая новость: читать код целиком вам не нужно. Плохая: совсем не читать нельзя. Между этими крайностями лежит навык выборочного чтения: вместо понимания каждой строки вы ищете в результате ответы на короткий список вопросов. Этому навыку и посвящена глава.
Сразу договоримся о цели. Цель чтения – ответ на один вопрос: понял ли исполнитель задачу. Непонимание видно сверху, без глубокого погружения, – как по расстановке мебели видно, что грузчики перепутали квартиры, ещё до проверки каждого ящика.
Чтение по слоям
Порядок фиксированный, четыре слоя, от поверхности вглубь. Он устроен так потому, что первые поломки почти всегда живут в одном из этих слоёв, а не в глубине алгоритмов.
Слой первый: что появилось. Ещё не открывая ни одного файла, посмотрите на их список. Сколько новых, сколько изменённых, совпадает ли это с ожиданием. Вы просили поиск на существующей странице – а в результате шесть новых файлов и какая-то новая папка? Стоп. Разговор здесь ещё даже не о качестве кода – о несовпадении масштаба: исполнитель понял задачу шире, чем вы ставили. Масштаб результата – самый быстрый индикатор понимания, и читается он за десять секунд.
Слой второй: где данные. Привычка знакома по первому вечеру, теперь она становится пунктом порядка. Что происходит с данными: появилось ли новое хранение, изменилась ли структура существующего, куда пишется и откуда читается. Правки в слое данных – самые дорогие в исправлении: код переписывается, а данные, записанные в неудачную структуру, приходится переносить. Если задача не предполагала изменений хранения, а они есть, – выяснять, зачем, раньше всего остального.
Слой третий: границы наружу. Всё, чем проект касается внешнего мира: адреса страниц, обращения к другим сервисам, письма, файлы на диске. Новая граница – это новое место, где проект может сломаться о реальность, и новое место, которое надо проверять. Появилась отправка почты, которой вы не просили? Обращение к внешнему сервису «для удобства»? Каждая такая граница должна быть или заказана вами, или объяснена, – третьего варианта нет.
Слой четвёртый: что при ошибке. Это третий вопрос первого вечера, дословно. Найдите глазами, что происходит, когда что-то идёт не так: пустой ввод, отсутствие записи, недоступная база. Не вникая в механику – просто убедитесь, что эти случаи в коде вообще существуют. Код, в котором предусмотрен только удачный путь, – это та самая картинка из первого вечера, только на уровень глубже: работает, пока всё хорошо.
Четыре слоя занимают десять-пятнадцать минут и не требуют читать алгоритмы. По их итогам у вас есть обоснованный ответ на главный вопрос – понял или не понял, – и список мест, куда смотреть пристальнее.
Объясни как маршрут
Теперь приём, который превращает агента из экзаменуемого в экскурсовода – и одновременно проверяет его работу лучше любого допроса:
Проведи меня по маршруту одного действия: человек заполнил форму
и нажал «Отправить». Что происходит дальше, шаг за шагом,
с указанием файла на каждом шаге?
Ответ – связный рассказ: браузер отправляет данные туда-то, их принимает такая-то функция в таком-то файле, проверяет то-то, пишет туда-то, отвечает тем-то. Ваша работа – идти по рассказу с открытыми файлами и сверять: этот файл существует? эта функция в нём есть? она действительно пишет туда, куда сказано?
Маршрут хорош тем, что линеен: его проверяют шаг за шагом, не держа в голове всю систему. И он мгновенно вскрывает разрыв между рассказом и кодом – а этому разрыву посвящён следующий раздел, самый важный в главе.
Отчёт – это гипотеза
Правило, ради которого стоило писать эту главу, мы сформулировали для себя после конкретного опыта, и расскажем его как есть.
Мы регулярно отдаём код на разбор моделям – свежий взгляд находит то, что замылилось. И в этих разборах, среди настоящих находок, стабильно попадаются два вида брака. Ложные тревоги: модель уверенно описывает поломку, которой нет, – например, потому что в постановке разбора была неточная вводная, и модель на неё добросовестно опёрлась. И выдумки: модель ссылается на строку, которой в файле не существует, или цитирует код, которого никто не писал, – уверенно, с номерами строк, с выводами. По нашим журналам это не редкость: в одном из разборов часть находок оказалась ложной, в другом модель забыла половину того паттерна, который бралась проверять.
С тех пор у нас действует правило без исключений: находка модели – это гипотеза. Документом является только сам код и результат запуска. Каждую находку, прежде чем чинить, мы сверяем с настоящим файлом и настоящим поведением. Чинить вслепую по отчёту запрещено – так можно «исправить» работающее. Дважды мы объявляли поломкой то, что работало исправно, и подробный разбор этих двух промахов ждёт в части про эксплуатацию.
Для вас это правило звучит так. Всё, что агент говорит о своей работе, – «я добавил проверку», «данные сохраняются», «этот случай обработан» – требует предъявления. Не потому что агент лжёт: он добросовестно описывает то, что собирался сделать, и его рассказ о намерении неотличим по тону от рассказа о сделанном. Разницу между намерением и фактом устанавливаете вы – взглядом в файл, запуском, тестом.
Практическое следствие для маршрута из прошлого раздела: расхождение между рассказом и кодом – находка, а не придирка. Если агент описывает шаг, которого в коде нет, вы поймали ровно тот зазор, из которого потом вырастают «странно, должно же работать».
Признаки непонимания
Короткий определитель. Пять признаков, каждый виден без чтения алгоритмов, каждый означает, что задача понята не так, – и чем раньше вы это признаете, тем дешевле выйдет.
Слишком много нового. Просили правку – получили россыпь файлов. Масштаб выдаёт додумывание.
Переименовано без просьбы. Ваши имена – из задачи, из файла правил, из прошлых шагов – заменены на «более правильные». Значит, агент работал от своих привычек, ваш проект он в этот момент не слышал.
Новые зависимости. В проекте появились сторонние библиотеки, которых никто не заказывал. Каждая – чужой код в вашем доме, и решение о вселении принимали не вы.
«На будущее». Заготовки, пустые функции, настройки «на вырост». Это объём без пользы: проверять нечего, а поддерживать придётся.
Ответ шире вопроса. Спрашивали про одно место – переделано три. Знакомо по прошлой главе: границы в задаче не было или она не удержала.
Что делать с плохим результатом
Последний раздел – о реакции, и он короткий, потому что правильная реакция одна.
Не спорить. Разговор в духе «ну я же просил по-другому, почему ты…» – потраченное время и захламлённый разговор: вы обсуждаете с исполнителем его прошлую ошибку вместо будущего результата. Модель не обучается от вашего недовольства внутри сессии – она просто получает ещё текста.
Вместо спора – сузить и переспросить. Взять свою же задачу, найти, где она позволила неверное толкование (обычно место находится – прошлая глава давала формулу, по которой искать), дописать границу или проверку и дать заново. Часто – в свежей сессии, чтобы неудачная попытка не тянулась следом. Переписанная задача плюс новый заход почти всегда дешевле, чем лечение неудачного результата серией уточнений: после трёх «нет, я имел в виду…» в разговоре лежат три слоя противоречащих указаний, и результат портится дальше.
И граница этого правила, чтобы оно не превратилось в привычку всё выбрасывать: если результат верен по сути и плох в деталях – детали правятся точечными задачами, это нормальная работа. Выбрасывать и переспрашивать стоит тогда, когда неверно понята сама задача.
Когда агент ходит по кругу
Отдельный случай, который стоит узнавать в лицо, потому что в нём теряют вечера. Агент чинит одно и ломает другое, потом чинит обратно и ломает первое. Или предлагает решение, которое вы уже отклонили двадцать минут назад, слегка переодетое. Или объяснения становятся всё длиннее, а изменений в файлах всё меньше.
Причина не в лени и не в упрямстве. Разговор к этому моменту забит противоречивыми обломками: три отвергнутых варианта, две ваши поправки, один недорассказанный отказ – и во всём этом модель ищет закономерность, которой нет. Она достраивает, как умеет, только теперь достраивает по мусору.
Правило простое: третья попытка исправить одно и то же место – сигнал останова. Не четвёртая и не седьмая. На третьей остановитесь и сделайте четыре вещи.
Первое: вернитесь к последнему состоянию, которое работало. У вас для этого есть история изменений, о которой мы поговорим в части II; пока достаточно знать, что откат – нормальный ход, а не поражение. Ковыряние в наполовину сломанном стоит дороже, чем возврат к целому.
Второе: смените жанр вопроса. Вместо «почини» попросите объяснить причину: «не меняй код, скажи, почему при таком-то действии происходит вот это, и назови два места, где может быть источник». Пока агент чинит, он подбирает; когда объясняет – ищет. Это разные занятия, и второе чаще выводит на настоящую причину.
Третье: перенесите задачу в свежую сессию – и возьмите с собой только факты: что делали, что ожидали, что получили, дословный текст ошибки. Отвергнутые варианты оставьте в прошлом разговоре: именно они и водили по кругу.
Четвёртое: если и свежая сессия закружилась – дело не в формулировке. Значит задача крупнее, чем выглядит, и её надо разбить: найти самый маленький шаг, который можно проверить отдельно, и сделать сначала его. Если разбить не получается, вы, скорее всего, наткнулись на границу, о которой пойдёт речь в последней главе этой части, – и лучшим решением будет отложить эту затею, а не победить её сегодня.
Отдельно про деньги и время: круг стоит дорого. Каждая попытка тратит и то и другое, а к пятой обычно уже сделан целый ворох правок, которых никто не считал. Правило трёх окупается тем, что превращает бесконечный вечер в двадцать минут и осознанное решение.
Если вы заказчик. Приём «проведи меня по маршруту» работает и с подрядчиком, дословно: «расскажите путь одной заявки от кнопки до менеджера, с названиями систем на каждом шаге». Знание кода не требуется – требуется готовность заметить, где рассказ становится туманным. Шаг, на котором звучит «ну там дальше это обрабатывается», – это то место, которое стоит попросить показать. И правило про гипотезу здесь то же: отчёт о работе и работа – разные вещи, предъявление разницы не обидит никого, кому есть что предъявить.
Упражнение. Откройте свой вечерний проект и попросите агента: «Объясни, что делает файл main.py и зачем в нём каждая функция». Затем проверьте рассказ по файлу, строка за строкой. Ищите два вида расхождений: сказано о том, чего в файле нет, и пропущено то, что есть. Найдёте хотя бы одно – вы своими глазами увидели зазор между отчётом и фактом на файле в сто строк. Помните об этом зазоре каждый раз, когда услышите уверенное «всё готово» о проекте в десять тысяч строк.
Вы умеете ставить задачу и читать результат. Но некоторые вещи приходится повторять агенту каждый раз: не трогай это, проверяй вот так, называй по-нашему. В следующей главе мы переселим эти повторения из вашей головы в проект – в файл правил, который агент читает сам. Заодно выяснится, что лучшие правила пишутся после ожогов, никогда заранее, и что наш собственный файл правил – это, по сути, дневник наших аварий.
Файл правил проекта
К этому моменту у вас накопились вещи, которые вы говорите агенту постоянно. Не трогай форму и сохранение. После правки прогони тест. Имена полей – как в проекте, не переименовывай. Каждая новая сессия начинается с того, что вы повторяете всё это заново, потому что агент, как мы выясним подробнее в следующей главе, между сессиями не помнит ничего.
Правило этой главы простое: всё, что вы объяснили агенту дважды, должно быть записано в проекте. В третий раз объяснять должен файл.
Что это такое
Файл правил – обычный текстовый файл в корне проекта, который агент читает перед началом работы и держит перед глазами всю сессию. Вы пишете туда указания один раз – агент подчиняется им в каждой сессии, не спрашивая и не забывая.
У этого файла есть устоявшееся отраслевое имя – AGENTS.md. Стоит знать, что это не особенность какого-то одного продукта: формат стал общим стандартом, передан в независимый фонд и читается парой десятков инструментов. Практический смысл для вас: правила, записанные однажды, переживут смену инструмента – новый агент прочтёт тот же файл. С одной оговоркой, которая стоит строки: пара крупных инструментов держится за собственное имя файла и общий стандарт не читает. Лечится это в одно действие – копией или ссылкой рядом, чтобы оба имени указывали на один текст; главное, чтобы правила не разъехались на две редакции, каждая со своей правдой.
Что туда пишут – по опыту, шесть разделов, все короткие:
Как запускать и как проверять. Команды запуска, команда тестов, что считается зелёным.
Что запрещено трогать. Файлы и области, которые меняются только по явной просьбе.
Обязательные действия. Что агент делает всегда, без напоминания: прогнать тесты после правки, зафиксировать рабочую точку после зелёного.
Соглашения об именах. Как называются поля, страницы, файлы – чтобы «более правильные» имена из привычек модели не расползались по проекту.
Стиль текстов, если проект что-то пишет людям: тон сообщений, язык, чего в текстах не бывает.
Куда что кладётся. Где живут страницы, где логика, где проверки – карта проекта в пять строк.
Для вечернего сервиса из части 0 файл правил выглядит так – целиком, без сокращений:
# Правила проекта
## Запуск и проверка
Запуск: uvicorn main:app --reload
Тесты: pytest. После любой правки кода - прогнать.
Зелёные тесты обязательны перед коммитом.
## Не трогать без явной просьбы
Форму отправки, сохранение в базу, файл test_zayavki.py.
## Имена
Поля формы: imya, kontakt, tekst. Не переименовывать.
Страницы: / (форма), /spisok (список). Новые - согласовать.
## Всегда
Одна задача - одна правка. За границу задачи не выходить.
Если нужна переделка работающего - сначала объяснить, не делая.
Семнадцать строк. Каждая сессия теперь начинается с этого файла, ваши повторения больше не нужны – и заметьте, что половина строк вам знакома: это библиотека формулировок из главы про постановку, переехавшая на постоянное место жительства.
Осадок ожогов
Теперь главная мысль главы, и она про то, откуда берутся правила, которые работают.
Наш собственный файл правил вырос до нескольких страниц. Читать его постороннему скучно: запреты, пороги, перечни, никакой философии. Но у почти каждой строки там есть дата рождения, и это дата аварии.
Строка «этот сайт собирается только своим сборщиком, чужим – запрещено» появилась после того, как два сборщика, писавшие в один файл стилей, оставили сто тридцать шесть статей без оформления; подробно этот случай мы разберём в части про изменения работающего проекта. Строка «не переименовывать поля – на именах держатся проверки» стоит там по той же причине, по которой вы сами задавали имена в задаче агенту: однажды переименованное поле обрушило проверки, и полчаса ушло на выяснение, почему красное то, что никто не трогал. Строка «проверять перезапуском, а не обновлением страницы» – после того как данные, «которые точно сохранялись», не пережили остановку службы. Ожог у каждой строки свой, и в файле он записан рядом одной фразой.
Мы называем это про себя «осадок ожогов», и в названии есть точность: правила не сочинялись – они выпали в осадок из настоящих потерь. Отсюда свойство, которое отличает их от правил из учебника: они соблюдаются. Правило, написанное «на всякий случай», не соблюдает никто, включая автора, – оно ничем не подкреплено, и рука обходит его без угрызений. Правило, написанное после ожога, помнит свою цену, и цена записана рядом одной фразой: нарушишь – получишь вот это, проверено тогда-то.
Отсюда же ответ на вопрос, который возникает у каждого, кто впервые слышит про файл правил: а что туда писать сначала? Ничего. Пустой файл с заголовком – нормальный старт. Правила придут сами, и глава подсказывает, откуда: первое же «я ведь это уже объяснял» – кандидат в файл. Заметили, что повторяетесь, – остановились, записали, продолжили. Файл растёт со скоростью ваших ожогов, и это правильная скорость: каждая строка в нём заработана.
Как записывать – три требования. В повелительном наклонении: «не трогать», «прогнать», «согласовать» – агент лучше слушается прямых форм. Коротко: правило длиной в абзац не прочтёт никто. И с причиной одной фразой: «не переименовывать поля – на именах держатся тесты». Причина превращает запрет из каприза в довод, а заодно напоминает вам самим через полгода, зачем это здесь.
Чего в файле не должно быть
Файл правил портится двумя способами, оба от усердия.
Первый – пересказ очевидного. Пожелания вроде «пиши чистый код», «делай хорошо», «следуй лучшим практикам» не значат ничего: агент и так старается по своим представлениям, а ваши представления в этих словах не выражены. Туда же – пересказ документации инструментов: агент её знает лучше вас. Каждая пустая строка в файле разбавляет полные: чем больше воды, тем меньше веса у настоящих запретов.
Второй – правила впрок, про ситуации, которых у вас не было. Они кажутся предусмотрительностью, а работают как шум: вы сами не помните, почему это здесь, и при первом неудобстве отменяете. Файл правил – не свод законов идеального проекта. Это память вашего конкретного проекта о его конкретных ошибках.
Проверка качества файла простая: уберите правило и посмотрите, станет ли больно. Правило, отмена которого ничего не меняет, было балластом.
Файл правил как имущество
И последнее, короткое. Взгляните на файл правил глазами части IV – как на предмет комплекта владельца.
README объясняет, как запустить. Список ограничений – что не сделано. Файл правил закрывает третий вопрос, который встанет у любого преемника: как здесь принято работать и на чём здесь уже обжигались. Человек, получивший проект с настоящим файлом правил, получает не только код – он получает прививки от аварий, которые ему теперь не обязательно повторять. В нашей ежедневной передаче между сессиями этот файл делает ровно эту работу: новая сессия не помнит вчерашних ошибок, но подчиняется правилам, которые из них выросли. Память стирается – осадок остаётся.
Если вы заказчик. Спросите подрядчика, есть ли в проекте файл правил для агентных инструментов, и попросите показать. Сам факт его существования говорит о зрелости процесса больше, чем портфолио: значит, здесь работают с агентами системно и записывают выводы из ошибок. А его содержимое – это, по сути, дневник того, на чём проект уже обжигался. Полезнейшее чтение перед тем, как принять работу.
Упражнение. Создайте в вечернем проекте файл правил из трёх заработанных строк, выдуманные не годятся: вспомните, что вы уже дважды говорили агенту за время этой книги, и запишите ровно это. Затем проверьте делом: начните свежую сессию, дайте задачу, которая раньше требовала напоминаний, – и посмотрите, соблюдены ли правила без единого слова с вашей стороны. Это упражнение занимает десять минут и меняет характер работы: с этого дня ваши объяснения накапливаются, вместо того чтобы испаряться.
Файл правил решает проблему повторения между сессиями. Но у беспамятства агента есть и второй этаж: внутри одной сессии его внимание тоже конечно, расходуется и к вечеру тупеет. Следующая глава – про контекст, память и стоимость: что агент на самом деле «видит», почему длинный разговор портится и как распределять работу между моделями, чтобы платить за силу только там, где она нужна. Заодно расскажем, как мы сами делим работу между моделями.
Контекст, память и стоимость
Прошлая глава несколько раз повторила «агент между сессиями не помнит ничего» и обещала объяснить. Объясняем – потому что из устройства памяти агента следует половина странностей, с которыми вы уже столкнулись, и почти все способы работать дешевле и лучше.
Понадобится одна картинка, без техники. У агента есть рабочий стол ограниченного размера – он называется контекстом. На столе лежит всё, что агент сейчас учитывает: ваша задача, файл правил, куски кода, которые он открыл, история текущего разговора, его собственные промежуточные рассуждения. Что на столе – то существует. Чего на столе нет – того для агента не существует вовсе: ни вчерашней сессии, ни соседней папки, ни ваших намерений, ни этой книги.
Вся глава – три следствия из этой картинки.
Следствие первое: длинный разговор тупеет
Стол конечен. Пока разговор короткий, на столе лежит нужное и только нужное: задача, правила, свежие файлы. К третьему часу работы там громоздится всё подряд: пять прошлых задач, три неудачные попытки, куски кода, который вы уже переписали, ваши уточнения, отменяющие друг друга. Новое кладётся поверх, старое уминается и теряет подробности – и агент начинает вести себя знакомым каждому образом: путает свежую версию со старой, «вспоминает» уже отменённые решения, отвечает всё более общо.
Это не поломка и не усталость в человеческом смысле. Это переполненный стол: среди наваленного труднее найти относящееся к делу, а утрамбованное старое теряет точность. Важное следствие для вашей интуиции: качество работы агента зависит от того, что лежит на столе, сильнее, чем от любой формулировки задачи. Блестящая постановка посреди захламлённой сессии проигрывает средней постановке в чистой.
Отсюда два рабочих правила.
Свежая сессия – бесплатное лекарство. Закончили задачу – зафиксировали результат – закрыли разговор. Новую задачу начинайте новым разговором: на столе окажутся файл правил, код в его текущем состоянии и одна задача. Всё нужное, ничего лишнего. Держать один бесконечный разговор «потому что он уже в курсе» – ложная экономия: «в курсе» на переполненном столе означает «путает».
Ссылка лучше пересказа. Не рассказывайте агенту, что в файле, – скажите, какой файл посмотреть: он положит на стол настоящий текст, а не ваш пересказ по памяти, который может расходиться с действительностью. Ровно из этого же правила растёт привычка предыдущей главы: правила живут в файле, а не в ваших повторениях, – файл всегда точен, память всегда примерно.
Следствие второе: между сессиями памяти нет
Закрыли разговор – стол очищен. Полностью. Следующая сессия начинается с пустого стола, и никакие «помнишь, мы вчера…» не работают: не помнит. Вчерашней сессии больше не существует.
Первая реакция на это – досада: как работать с исполнителем, который каждый день всё забывает? Ответ на неё дала глава о файле правил. Беспамятство лечится имуществом проекта, память тут и не нужна: файл правил помнит, как здесь принято работать; README – как запускать; список ограничений – что не сделано; история изменений – что и когда менялось. Сессия, начавшая с пустого стола, кладёт на него эти четыре вещи и через минуту знает о проекте всё, что нужно для работы.
У нас проект каждый день переходит к сессии, которая не помнит ничего, и это оказалось той же задачей, что передача проекта человеку, – к ней мы вернёмся в последней части. Здесь важна обратная сторона: всё, что вы делаете для агента – правила, README, журнал решений, – автоматически оказывается сделанным для любого будущего человека. Дисциплина работы с беспамятным исполнителем и дисциплина передачи – одна и та же дисциплина. Вы получаете вторую бесплатно.
Следствие третье: сила стоит денег, и её надо тратить прицельно
Агентная работа платная – по подписке или за объём, неважно: важно, что сильная модель дороже слабой, а длинная сессия дороже короткой. Цен и названий мы по правилам этой книги не называем – они устареют раньше тиража. Называем принципы, они держатся годами.
Главный принцип: сила модели должна соответствовать задаче, а не вашей тревоге. Тревога подсказывает всегда брать самую сильную – «чтобы наверняка». На деле у большинства задач вечернего проекта есть уровень, выше которого разницы нет: переименовать, добавить поле, написать простую страницу одинаково сделает и средняя модель, и великая. А есть задачи, где разница драматична: спроектировать структуру, распутать поломку, вычитать текст на повторы.
Наше рабочее правило распределения, целиком: механическую работу – дешёвой модели; тонкую, где важен вкус или глубина, – дорогой; проверку сделанного – другой модели, чем та, что делала. Последняя часть неочевидна и важнее двух первых: исполнитель плохо проверяет сам себя, и дело здесь в положении, сила ни при чём. Тот, кто написал, смотрит на текст изнутри своего замысла и видит замысел; свежий взгляд видит текст.
Так мы работаем сами: структуру задач и разборов поручаем одной модели, тонкую работу со словом – другой, а проверку сделанного всегда третьей, со своим чистым столом. Ни одна из этих ролей не взаимозаменима с другой, и общий счёт при таком разделении ниже, чем если бы всё делала самая дорогая модель.
К принципу прилагается правило эскалации, выстраданное: если задача не поддалась с двух заходов – дело уже вряд ли в формулировке. Третья попытка «сказать то же самое другими словами» стоит денег и обычно не помогает. Помогают два хода: взять модель сильнее – или разрезать задачу на части, каждая из которых по зубам текущей. Часто второе лучше первого: задача, которая не даётся, обычно велика, и это лечится делением; по-настоящему сложные встречаются реже, чем кажется.
Если вы заказчик. Из этой главы следует вопрос к смете подрядчика, работающего с агентами: «как у вас распределены модели по задачам?» Ответ «мы всё делаем самой мощной» означает, что вы оплачиваете стрельбу из пушки по воробьям; ответ с распределением – признак считающего процесса. Второй вопрос: «кто проверяет сделанное – та же модель или другая?» Теперь вы знаете, почему это важно.
Упражнение. Проведите опыт на собственном агенте. Возьмите один и тот же вопрос средней сложности о вашем проекте – например, «объясни, как устроено хранение обращений и что произойдёт при двух одновременных отправках». Задайте его дважды: первым сообщением в свежей сессии – и тем же текстом в конце длинной рабочей сессии, где вы час правили код. Сравните два ответа: полноту, точность, конкретность. Разница, которую вы увидите, – это цена захламлённого стола, и после этого опыта закрывать сессии станет легко.
Остался последний источник хаоса, о котором мы пока говорили вскользь: вторая сессия. Стоит открыть два окна – и у вашего проекта уже двое исполнителей, которые не знают друг о друге, а общие файлы знают обоих. Следующая глава – про работу нескольких рук на одном проекте: почему это наступает раньше, чем вы будете готовы, и какая дисциплина спасает.
Несколько рук на одном проекте
Эта глава могла бы стоять в конце книги, в разделе для продвинутых, – так обычно и делают, потому что «работа в команде» звучит как забота больших проектов. Мы ставим её в первую часть, и на то есть причина, проверенная на себе: несколько рук на проекте появляются раньше, чем вы успеваете подготовиться. Для этого не надо никого нанимать. Достаточно открыть второе окно.
Выглядит это невинно. В одном окне агент делает долгую задачу – скажем, переделывает страницу списка. Вам скучно ждать, и во втором окне вы просите другого агента поправить мелочь – текст сообщения, цвет кнопки. Поздравляем: у вашего проекта теперь двое исполнителей. Они не знают друг о друге. Проверять друг друга они не умеют. А файлы у них общие.
Дальше происходит то, что в командах происходило десятилетиями, только быстрее. Оба читают файл в одном состоянии, оба правят своё, оба сохраняют – и чья запись легла второй, того и файл. Работа первого исчезает без звука: ни ошибки, ни предупреждения, просто в файле её больше нет. Вы узнаете об этом позже – когда «уже же починенное» окажется сломанным, и никто не сможет объяснить, как.
У нас эта механика встречается в журналах не раз, и подробный разбор ждёт в части про изменения работающего проекта. Здесь достаточно короткого: параллельная сессия способна похоронить чужую работу молча, и особенно коварен отложенный вариант – когда правка на месте в момент проверки и исчезает позже, потому что вторая сессия сохранила поверх неё своё, взяв за основу устаревшую копию.
Из-за скорости агентов старая командная проблема стала злее: человек правит файл минутами и часами, агент – секундами, окна конфликтов стали чаще, а привычки защищаться у одиночки нет. Вырабатываем.
Дисциплина: три правила
Одна задача – одно окно – своя территория. Главное правило, оно предотвращает большинство конфликтов до их рождения. Двум одновременным сессиям нельзя давать задачи с пересекающейся областью правки. Границы, которые вы и так пишете в каждой задаче с главы о постановке, здесь получают вторую работу: это не только забор для агента, но и раздел территории между агентами. «Меняй только страницу списка» в одном окне и «меняй только тексты сообщений» в другом – два непересекающихся участка; конфликтовать негде. Если же две задачи тянутся к одному файлу – не запускайте их одновременно, сделайте по очереди. Очередь медленнее на минуты и дешевле на часы.
Фиксировать чаще, чем кажется нужным. Коммит – ваша единственная защита от молчаливой потери: затёртое в файле восстанавливается из истории за минуту, если оно в историю попало. Правка, не попавшая в коммит, не защищена ничем, и при параллельной работе это утраивается. Рабочий ритм таков: перед запуском второй сессии – коммит; после каждого принятого результата – коммит. Пусть их будет много и мелких: история изменений не музей, её не надо украшать.
После параллельной работы – сверка, а не вера. Обе сессии закончили, обе отчитались, всё выглядит хорошо. Теперь единственный достоверный источник – состояние файлов, и смотреть надо его: что изменилось суммарно, живы ли обе правки, прогоняются ли тесты. И правило перепроверки через время: к важной правке вернуться через полчаса и убедиться, что она всё ещё на месте. Звучит параноидально ровно до первого случая, когда окажется, что уже нет.
Отраслевой ответ: у каждой задачи свой каталог
Для случаев, когда параллельность нужна всерьёз и надолго, у отрасли есть решение получше очереди, и о нём стоит знать даже до того, как оно понадобится.
Идея простая: развести сессии по копиям проекта, вместо раздела по задачам. Система контроля версий умеет создавать несколько рабочих каталогов одного проекта – каждый со своей копией файлов, но с общей историей. Сессия работает в своём каталоге и физически не может затереть чужой: файлы разные. Когда задача готова, её результат вливается в общую историю осознанным действием – вы смотрите, что вливается, и конфликт, если он есть, разрешается на ваших глазах, а не молча в момент сохранения.
Переводя на язык картинок: вместо двух поваров у одной разделочной доски – две доски и общая кладовая, куда готовое сдают через окошко. У окошка стоите вы.
Для вечернего проекта это обычно избыточно – правила из предыдущего раздела покрывают его с запасом. Но знать, что приём существует и как называется («рабочие деревья», worktree, в терминах git), полезно: в тот день, когда вы захотите гонять три задачи параллельно, вы будете искать решение по имени, а не изобретать.
Агент в фоне
Отдельный случай нескольких рук, который выглядит иначе, а устроен так же: долгая задача, запущенная в фоне. Вы поручили агенту большую работу – прогнать проверку по всем страницам, переделать сотню записей – и занялись другим. Рук снова две: ваша и фоновая, и фоновая финиширует в непредсказуемый момент.
Два правила на этот случай. Первое: фоновая задача получает свою территорию так же, как параллельная сессия, – границей в постановке. Второе, менее очевидное: у фоновой работы должен быть однозначный признак завершения и место, куда она кладёт результат, – файл отчёта, запись, отметка. Иначе получается фигура, которой в этой книге отведена отдельная глава: работа, о состоянии которой ничего не известно. «Кажется, оно ещё работает» и «кажется, оно закончило» – два состояния, в которых нельзя принимать решения.
И примета времени, чтобы глава не выглядела страшилкой: параллельность – это хорошо. Агенты снимают главное ограничение одиночки – последовательность: впервые один человек может вести три работы одновременно, как маленькая команда. Вся глава сводится к тому, что вместе с возможностями команды приходят и обязанности бригадира: делить территорию, вести общую историю, сверять результат. Обязанности небольшие. Возможности – нет.
Если вы заказчик. Если над вашим проектом работает несколько исполнителей – людей, агентов, вперемешку, – один вопрос вскрывает зрелость процесса: «как вы делите работу, чтобы не затирать друг друга, и как вливаете результаты?» В ответе должны прозвучать территории и осознанное слияние. Ответ «мы аккуратно» вы теперь умеете переводить сами.
Упражнение. Устройте конфликт нарочно, на учебном проекте, – лучше один раз увидеть. Откройте два окна агента. В первом попросите изменить заголовок страницы списка, во втором, не дожидаясь, – изменить в том же файле текст под заголовком. Примите оба результата и откройте файл: с высокой вероятностью одна из правок исчезла. Посмотрите историю (git log), найдите потерянное в разнице между версиями (git diff) и верните файлы к последней зафиксированной точке командой git checkout -- . Весь опыт занимает десять минут и оставляет то, что не оставляет никакое чтение: память о том, как выглядит молчаливая потеря – и как легко она чинится, когда есть история.
Осталась одна глава – о том, что всем этим рукам поручать. Она короткая, потому что рабочего правила там на страницу: делайте то, что сможете проверить сегодня вечером.
Рамка: что поручать всем этим рукам
Про то, каким должен быть объём первой версии, написаны целые книги, и у этой темы есть неприятное свойство: чем больше о ней читаешь, тем меньше делаешь. Поэтому здесь будет короткая глава с одним рабочим правилом, уже прозвучавшим в конце прошлой: делайте то, что сможете проверить сегодня вечером.
Правило выглядит слишком простым для решения, о котором столько спорят. Разберём, почему оно работает – и почему именно с агентами оно стало важнее, чем было когда-либо.
Почему рамку рвёт именно сейчас
У прежнего разработчика-одиночки был встроенный ограничитель аппетита: скорость рук. Задумать можно было что угодно, но каждый пункт задуманного стоил вечеров, и список хотелок редел сам собой, об усталость.
Агент этот ограничитель снял. Попросить «ещё и личный кабинет, и уведомления, и статистику» стало так же дёшево, как не попросить, – и код появится, много кода, быстро. Ограничитель переехал в другое место, и вся эта книга последовательно показывала куда: в проверку. Сгенерировать можно сколько угодно; проверить – сколько успеете. Всё, что сгенерировано и не проверено, вы уже видели в первый вечер: это картинка, у неё нет обязательств.
Отсюда и правило вечера. Объём шага определяется не фантазией и не скоростью генерации – ёмкостью вашей проверки. Что сможете сегодня прогнать руками и тестом, то сегодня и существует. Остальное – план.
Три строки вместо технического задания
Рамка первой версии – или второй, или любого следующего рывка – умещается в три строки, и все три вам уже знакомы по отдельности:
Кто один. Один пользователь, чьей рукой вы будете проверять. Для сервиса обращений это был «человек, у которого что-то случилось». Попытка угодить двоим сразу – заявителю и менеджеру, покупателю и складу – удваивает даже не работу: количество непроверенного.
Что одно. Один сценарий от начала до конца: отправил – сохранилось – увидели – отметили. Сквозной путь – к нему мы ещё вернёмся, когда речь пойдёт о проверках; здесь он служит мерой объёма: версия – это один проходимый путь; набором возможностей она станет позже, по одному за раз.
Чем проверите. Критерий готовности, сформулированный до начала работы, проверяемый и скучный: «обращение с сайта доходит до списка и переживает перезапуск». В главе о постановке этот пункт назывался проектированием краёв; здесь добавим второе его свойство: он останавливает. Версия, у которой критерий выполнен, готова – и всё, что чешется доделать, идёт в следующую.
Три строки плюс список «что не входит» из части 0, который к этому месту книги дорос до постоянного инструмента: письменная граница снимает зуд, потому что отложенное решением перестаёт быть отложенным по слабости.
Ловушка «ещё одной функции»
Главный враг рамки не лень и не нехватка сил – прилив сил. Всё работает, агент послушен, вечер молод, и рука сама тянется: раз так легко, добавим ещё фильтры. И роли. И красивое оформление. И вход по паролю.
Механика уже разобрана по частям книги, соберём её в одно место. Каждая добавка приносит свои края, которые надо продумать; свои проверки, которые надо написать и гонять; своих соседей, которых она задевает; свои состояния, которым нужно место в отчёте. Функции складываются, а их стоимость перемножается – и наступает вечер, когда проект перестаёт помещаться в вашу проверку целиком. С этого вечера вы больше не знаете, работает ли он. Знаете только, что работал.
Вечерние проекты умирают от добавления многократно чаще, чем от нехватки. Недоделанный проект с одним работающим сценарием живёт: им пользуются, его развивают. Переделанный, где семь сценариев по половине, доживает до первого настоящего пользователя.
Как выглядит рамка, которой не было
Обещанный пример из нашей практики – с необычной стороны. В последней части будет разговор об отпущенном направлении: группе сайтов, которую мы свернули, потому что месяцы работы не привели ни одного человека. Забежим вперёд и посмотрим на ту историю глазами этой главы: что было бы, поставь мы рамку в начале.
Рамка звучала бы так: один сайт, один сценарий – человек ищет услугу, находит страницу, оставляет заявку, – критерий: столько-то настоящих переходов и хотя бы одна заявка за месяц. Проверка стоила бы один сайт и один месяц. Вместо этого строилась сеть: генерация статей, карты сайтов, перелинковка – работа на месяцы, добротная, местами изящная. Проверка предположения «люди придут этим путём» откладывалась, потому что строить было интереснее, чем проверять, – знакомый мотив? Это «ещё одна функция», только на уровне целого направления. Когда проверка наконец случилась, она стоила всего построенного.
Годится эта история как масштабная линейка: ловушка добавления одинаково устроена на кнопке, на функции и на группе сайтов. Меняется только цена вечера, в который выясняется правда.
Когда агента лучше не звать
Книга про работу с агентом обязана сказать и обратное: есть задачи, где он – неподходящий инструмент. Не потому, что не справится, а потому, что справится убедительно, и вы этого не заметите.
Когда вы не умеете отличить верный ответ от правдоподобного. Это главный признак, и он обходится дороже всех прочих. Расчёт налога, формулировка договора, дозировка, инженерный расчёт нагрузки – агент выдаст связный, уверенный, оформленный ответ. Проверить его вы не сможете, потому что не знаете, как выглядит правильный. Здесь работает то же правило вечера, только жёстче: не поручайте того, чего не сможете проверить – ни сегодня, ни в принципе. Выход не в лучшей формулировке запроса, а в человеке, который в этом разбирается, или в собственном обучении, если тема ваша надолго.
Когда ошибку нельзя отменить. Отправка писем живым людям, списание денег, удаление данных, публикация от лица компании. Проверять такое надо до, а не после, и цена невнимательности здесь не измеряется вечером. Мы это правило вписали в файл правил жирным – после трёх случаев, когда очередь публикаций отправляла подготовленное немедленно. Действие, которое нельзя откатить, либо выполняет человек своей рукой, либо оно проходит через подтверждение, которое человек даёт осознанно.
Когда задача уже решена миром. Приём платежей, рассылка писем, вход через известные сервисы, сбор статистики. Агент напишет вам своё – и напишет быстро; вопрос в том, что дальше это своё придётся содержать: следить за изменениями на чужой стороне, латать безопасность, разбираться, почему у одного человека из ста не работает. Готовый сервис берёт эту работу на себя за деньги, и в подавляющем большинстве случаев эти деньги дешевле вашего внимания. Генерация сделала дешёвым написание кода. Эксплуатацию кода она не подешевила совсем – это, если коротко, вся мысль этой книги.
Когда нужно решение, а не код. Стоит ли делать это направление, тот ли это пользователь, отпускать ли проект – агент прекрасно разложит доводы, но выбор остаётся за владельцем, и он не пишется на языке программирования. Спрашивать совета полезно; передавать решение – нет.
Когда вы торопитесь и устали. Отдельный случай, которому в части III посвящена целая глава: в спешке проверяют хуже всего, а агент в спешке особенно охотно достраивает пробелы. Вечер, начатый словами «сейчас быстренько», – худшее время для поручений.
Обратная сторона, чтобы список не читался как запрет: во всём остальном звать агента стоит смелее, чем кажется. Скучная переделка, разовый скрипт, разбор чужого кода, черновик, второе мнение, объяснение непонятного – здесь он даёт выигрыш, ради которого всё это и затевалось.
Если вы заказчик. Предложение подрядчика на двадцать пунктов – повод для одного вопроса: «какой из пунктов проверяет главное предположение – что этим вообще будут пользоваться – и можно ли начать с него одного?» Хороший исполнитель ответит, какой и как. Уклончивый ответ означает, что проверка предположения отложена в конец, – а вы теперь знаете, сколько она стоит в конце.
Упражнение. Опишите вторую версию своего вечернего сервиса тремя строками: кто один, что одно, чем проверите. Всё остальное, что просилось в неё, – в список «не входит», письменно. Потом сверьте объём с правилом вечера: успеете проверить сегодня? Если нет – режьте сценарий, пока не влезет. Занимает десять минут.
На этом ремесло собрано целиком. Вы умеете ставить задачу и держать её в границах, читать результат и не верить отчётам, копить правила в файле, распоряжаться вниманием и силой моделей, дирижировать несколькими руками и – с этой главы – выбирать, что вообще делать. Инструмент освоен.
Дальше – часть II, инженерия, и у перехода простая логика: ремесло позволяет получать нужный результат, инженерия – его не терять. Система контроля версий как страховка от всего, что вы прочли про параллельные руки. Проверки, которые охраняют проект, пока вы спите. Данные, секреты и выкладка на настоящий сервер. И последнее звено – чтобы всё это давало результат: чтобы вас нашли, вам поверили и вы это видели. Всё то, из-за отсутствия чего вечерние проекты остаются вечерними.