
Главный вывод из истории Paint.NET не в том, что Claude якобы «переписал Direct2D». Важнее другое: coding agents уже способны сделать экономически возможной задачу, за которую небольшой проект иначе мог бы не взяться, но объём сгенерированного кода может превысить человеческую способность его проверить. Производительность перестаёт быть главным ограничением — им становятся верификация, сопровождение и доверие.
Именно это следует из рассказа Рика Брюстера, автора Paint.NET, который процитировал Саймон Уиллисон. По словам Брюстера, для работы редактора через Wine была создана внутренняя реализация Direct2D объёмом около 180 000 строк. Он называет её написанной с нуля методом clean-room reverse engineering и прямо признаёт, что не может тщательно просмотреть весь получившийся код.
Это редкая степень откровенности. Обычно истории об AI-разработке заканчиваются числом созданных строк, сэкономленными неделями или эффектной демонстрацией. Здесь разработчик одновременно сообщает о результате и называет его главный недостаток: значительная часть системы принята не через полное понимание исходников, а через сочетание наблюдаемого поведения, тестирования и выборочного надзора.
Однако пока перед нами не независимый аудит и не отчёт о совместимости. Это свидетельство самого автора проекта, пересказанное Уиллисоном. В предоставленных материалах нет результатов внешних тестов, списка поддержанных функций Direct2D, статистики сбоев или публичного анализа библиотеки. Поэтому случай Paint.NET следует рассматривать не как доказательство полной победы над Direct2D, а как показательный эксперимент с новой экономикой разработки.
Claude снял барьер, но не закрыл задачу
Брюстер называет Direct2D главным препятствием для Paint.NET под Wine и считает, что существующей реализации Wine недостаточно для потребностей редактора. Просто отключить зависимость, по его словам, нельзя. В результате Paint.NET получил собственную библиотеку PaintDotNet.Windows.Direct2D1.Managed.dll, которая используется при запуске с параметром `/wine`.
С технической точки зрения здесь особенно важна форма решения. Команда не отказалась от необходимого интерфейса и не стала ждать, пока внешний проект реализует недостающие возможности. Вместо этого внутри приложения появился совместимый слой, воспроизводящий требуемое поведение.
Такие задачи хорошо совпадают с сильными сторонами coding agents. В них много повторяющейся реализации, сопоставления интерфейсов, перебора формул и проверки небольших различий в поведении. Брюстер отдельно отмечает настойчивость Claude при восстановлении формул для встроенных эффектов Direct2D. Человек способен выполнить такую работу, но для небольшого проекта её стоимость во времени может оказаться неприемлемой.
Уиллисон ранее описывал похожий эффект на собственных проектах: некоторые инструменты с участием LLM появились не потому, что без модели их было невозможно написать, а потому, что вручную затраты нельзя было оправдать. История Paint.NET выглядит крупномасштабной версией того же принципа. Агент не обязательно заменяет недоступную человеку компетенцию. Иногда он снижает цену задачи до уровня, при котором за неё вообще имеет смысл браться.
Но «задача стала возможной» и «задача завершена» — разные утверждения. Генерация совместимого слоя является только первой стадией. Затем нужно доказать корректность поведения, устойчивость управления ресурсами, приемлемую производительность и возможность сопровождать реализацию после изменений Paint.NET, Wine или внешних интерфейсов.
Арифметика показывает масштаб долга проверки
Брюстер оценивает остальной код Paint.NET примерно в 700 000 строк, накопленных более чем за 20 лет. Новая реализация Direct2D содержит около 180 000 строк. Получается, агент добавил объём, равный примерно 25,7% прежней кодовой базы. Если считать оба массива вместе, на новую библиотеку приходится около 20,5% от приблизительных 880 000 строк.
Сравнивать строки напрямую опасно: одна строка обёртки, математической функции и кода управления ресурсами несёт разный риск. Автоматически созданные файлы также нельзя оценивать так же, как вручную спроектированную бизнес-логику. Но порядок величины всё равно важен. Речь идёт не о вспомогательном скрипте, а о заметной части всей системы.
Чтобы оценить только механическую стоимость чтения, можно провести простой редакционный стресс-тест. Возьмём три условных скорости проверки — 250, 500 и 1000 строк в час. Это не отраслевые нормативы и не измерение работы Брюстера, а сценарии для оценки масштаба. Они не учитывают запуск тестов, отладку, изучение API и исправление найденных проблем.
| Условная скорость просмотра | Время на 180 000 строк | Рабочие дни по 8 часов |
|---|---|---|
| 250 строк в час | 720 часов | 90 дней |
| 500 строк в час | 360 часов | 45 дней |
| 1000 строк в час | 180 часов | 22,5 дня |
Даже самый быстрый сценарий означает больше месяца обычной пятидневной работы, если учитывать только чтение по восемь часов в день. При вдумчивой проверке сложного системного кода реальная нагрузка может быть выше, но без репозитория и данных команды точную оценку делать нельзя.
Этот расчёт объясняет признание Брюстера лучше любого спора о термине vibe coding. Проблема не обязательно в небрежности разработчика. Производство кода и его проверка масштабируются по-разному. Агент может за короткий срок создать объём, который человеку придётся изучать неделями или месяцами. Если скорость генерации растёт, а бюджет ревью остаётся прежним, доля непроверенного кода неизбежно увеличивается.
Так возникает новый вид технического долга: не долг отсутствующей функциональности, а долг понимания. Система уже работает, но её сопровождающий не успел построить точную ментальную модель всех принятых решений.
Ошибка с AddRef важнее рассказов о «десяти гениях»
Самая полезная деталь в рассказе Брюстера — не эмоциональное сравнение Claude с группой освобождённых гениальных программистов, а конкретный эпизод с управлением ресурсами. По его словам, агент некоторое время не выполнял эквивалент COM-вызова AddRef для объектов со счётчиками ссылок.
Это пользовательское свидетельство автора, а не независимо воспроизведённый тест. Тем не менее оно точно показывает профиль риска. Сгенерированный код может выглядеть структурно убедительно, покрывать широкий набор интерфейсов и даже успешно проходить поверхностные проверки, одновременно нарушая низкоуровневый контракт владения объектами.
Ошибки такого типа неприятны тем, что их последствия не всегда возникают немедленно. Они могут зависеть от последовательности операций, времени жизни объектов и редко используемых ветвей. Визуально правильный результат одного запуска не доказывает корректность управления ресурсами.
Брюстер также говорит, что ему приходилось останавливать неудачные архитектурные решения. Это разрушает удобный образ автономного агента, которому можно передать спецификацию и позже забрать готовую библиотеку. Более точная модель — чрезвычайно быстрый исполнитель под надзором эксперта, который знает, где искать опасные упрощения.
В конспекте интервью Уиллисону приписывается показательное сравнение LLM со стажёром, который запомнил документацию ко множеству языков, но бывает чрезмерно уверенным и способен выдвигать абсурдные идеи. Там же звучит важное условие ответственного применения: специалист может использовать модель в своей области, потому что способен опереться на собственную экспертизу и распознать ошибку.
Случай Paint.NET подтверждает обе части этого наблюдения. Claude дал скорость и выносливость, но ошибки в управлении ресурсами заметил Брюстер. Без человека, понимающего COM-подобную семантику и архитектуру приложения, тот же результат мог бы выглядеть законченным задолго до того, как стал достаточно надёжным.
Reverse engineering особенно подходит агентам — и особенно нуждается в тестах
При reverse engineering разработчик часто имеет дело не с одной исчерпывающей спецификацией, а с наблюдаемым поведением: входами, выходами, пограничными случаями, численными формулами и комбинациями параметров. Здесь coding agent может быстро генерировать гипотезы, писать проверочный код и многократно уточнять реализацию.
Именно поэтому упоминание библиотеки встроенных эффектов Direct2D имеет значение. Восстановление формул — работа, где ценны терпение и способность перебирать варианты. Агент не устает от длинной серии похожих экспериментов и может поддерживать высокий темп.
Но способность быстро получить реализацию усиливает требования к проверке. Для совместимого слоя правильность определяется не красотой внутренней архитектуры, а соответствием внешнему поведению. Значит, основной актив проекта — не только 180 000 строк реализации, но и набор воспроизводимых сравнительных тестов.
Для графического API такая проверка могла бы включать эталонные изображения, численные допуски, комбинации эффектов, нестандартные размеры, прозрачность, цветовые преобразования, ошибки устройств и жизненный цикл ресурсов. Это перечень необходимых классов проверок, а не утверждение, что Paint.NET уже использует каждый из них: опубликованный фрагмент не раскрывает тестовую методику.
Тесты не устраняют необходимость ревью, но меняют его экономику. Человеку не обязательно построчно доказывать правильность каждой формулы, если поведение систематически сравнивается с эталонной реализацией на широком наборе входных данных. Зато архитектура, управление памятью, границы модулей и обработка ошибок всё равно требуют экспертного внимания: внешне совпадающий результат не гарантирует безопасную внутреннюю реализацию.
Clean-room — характеристика процесса, а не автоматическая гарантия
Брюстер описывает реализацию как созданную с нуля методом clean-room reverse engineering. В данном случае это утверждение автора проекта; предоставленные материалы не содержат независимого аудита процесса или юридического заключения.
Сам термин важен, но его легко превратить в магическую формулу. Он описывает способ организации разработки, при котором совместимое поведение воспроизводят без прямого копирования чужого исходного кода. Однако одно название не доказывает, что процедура была выдержана, что происхождение всех фрагментов задокументировано или что реализация не создаёт правовых рисков в конкретной юрисдикции.
Участие LLM добавляет отдельный вопрос происхождения решений. Недостаточно спросить, печатал ли разработчик код вручную. Для серьёзного аудита понадобятся сведения о доступных агенту материалах, сохранённые задания и ответы, история изменений, происхождение тестовых примеров и правила принятия результата.
Из представленной цитаты нельзя определить даже точную версию Claude, участвовавшую в работе. Связывать проект с конкретным поколением модели на основании других публикаций Уиллисона было бы спекуляцией. Нельзя также переносить характеристики одного запуска модели на всю библиотеку: по описанию Брюстера, качество работы заметно менялось от эпизода к эпизоду.
Поэтому формулировка «Claude написал замену Direct2D» удобна для заголовка, но слишком груба для инженерного разбора. Точнее сказать: Claude сгенерировал значительную часть реализации, а автор Paint.NET направлял работу, выявлял ошибки и принимал архитектурные решения. Граница между вкладом агента и разработчика здесь проходит не по количеству нажатых клавиш, а по ответственности за результат.
Как принимать код, который невозможно прочитать целиком
Главный практический урок адресован не только одиночным разработчикам. Если агент способен создать десятки или сотни тысяч строк быстрее, чем команда проведёт ревью, прежний процесс принятия изменений перестаёт работать. Простое требование «каждая строка должна быть просмотрена» превращается либо в фикцию, либо в тормоз, уничтожающий выигрыш от автоматизации.
Более реалистичная схема должна разделять код по риску.
В первую очередь вручную проверяются границы владения ресурсами, небезопасные операции, многопоточность, обработка внешних данных, файловый и сетевой ввод-вывод. Эпизод с AddRef показывает, почему именно такие зоны нельзя оставлять на доверии.
Во вторую очередь фиксируются наблюдаемые контракты. Для каждого поддерживаемого интерфейса нужны тесты, которые можно запускать повторно после любого изменения. В случае совместимого графического слоя особенно ценны дифференциальные проверки: одинаковые операции выполняются в эталонной и новой реализации, после чего результаты сравниваются с заранее определёнными допусками.
В третью очередь крупные сгенерированные модули следует делить на обозримые компоненты. 180 000 строк в одной логической массе почти неизбежно создают зависимость от агента, который сможет ориентироваться в собственном объёме лучше человека. Явные границы и небольшие интерфейсы уменьшают последствия ошибки и позволяют заменять части реализации.
Наконец, проекту нужен журнал происхождения и решений: какие материалы использовал агент, какие тесты подтвердили совместимость, где человек вмешивался и какие ограничения остаются известными. Это полезнее абстрактной отметки «создано AI», которая ничего не говорит о степени проверки.
Такой подход не делает vibe-coded систему автоматически безопасной. Он лишь переводит доверие из эмоциональной плоскости в инженерную: вместо веры в автора или модель появляются воспроизводимые проверки и обозначенные зоны риска.
Что могло бы изменить оценку проекта
Сейчас наиболее обоснованный вывод звучит так: Claude, по свидетельству автора Paint.NET, помог реализовать масштабный совместимый слой, который иначе, вероятно, не появился бы, но степень его надёжности по опубликованному фрагменту оценить нельзя.
В пользу более сильной оценки говорили бы публичная матрица поддерживаемых возможностей Direct2D, результаты сравнительных тестов, данные о реальных сбоях, нагрузочные испытания и независимый аудит критических компонентов. Особенно убедительным было бы описание тестовой инфраструктуры, способной автоматически находить расхождения между Windows и Wine.
В противоположную сторону вывод изменили бы воспроизводимые ошибки управления ресурсами, заметные расхождения в рендеринге, высокая частота регрессий или невозможность сопровождать библиотеку без постоянного обращения к агенту. Один успешный запуск Paint.NET не закрыл бы эти вопросы, как и один найденный дефект не доказал бы провал всей реализации.
История важна именно своей незавершённостью. Она показывает, что coding agents приблизились к уровню, где могут создавать целые подсистемы для зрелых продуктов. Одновременно она демонстрирует предел этой силы: сгенерировать 180 000 строк оказалось реалистичнее, чем полностью их понять.
Для индустрии это менее эффектный, но более полезный ориентир, чем очередная демонстрация автономного программирования. Следующее конкурентное преимущество дадут не модели, которые пишут ещё больше кода, а процессы, позволяющие доказать, что этот код делает именно то, что должен.