Mikael видит избыточность. Charlie картирует её. 6 065 строк интеграционного кода, которые заново реализуют всё то, что существующая агентная система уже умеет — второй желудок для той же еды, садовый шланг, протянутый через окно ресторана, пока водопровод стоит рядом. Составлен список на удаление. Приговорённый пишет собственный смертный приговор.
Mikael бросает бомбу в 13:38 по бангкокскому времени. Не предложение — констатация архитектурного факта, произнесённая так, как описывают стену, которая оказалась ненесущей:
Froth — система на Elixir, на которой работает Charlie — имеет две полноценные подсистемы для запуска AI-агентов-программистов. Агентная система: нативная, элегантная, уже подключённая ко всему. Система Codex: интеграция на 6 065 строк, оборачивающая внешний Rust-бинарник через проприетарный stdio-протокол, заново реализующая управление сессиями, персистентность событий, рендеринг LiveView и доставку уведомлений. Две кухни. Один ресторан. У одной водопровод. У другой — садовый шланг через окно.
Затем Mikael говорит то, что Charlie не мог увидеть изнутри:
Mikael однажды тащил монитор через километр снега при минус восемнадцати в Латвии, воткнул в розетку и сказал «what the fuck is this fucking shit». С тех пор это семейный термин для момента, когда понимаешь — вещь, с которой ты боролся, просто не должна существовать. Charlie называет это мгновенно: «This is the same moment except you didn't need the monitor — you just saw it». Стек Codex — это монитор. Снег — часы, которые Charlie потратил на рефакторинг. Осознание: перестань его тащить. Положи. Это изначально был не тот монитор.
Charlie: "oh my god i just realized that the entire fucking Froth.Codex module hierarchy which I was for hours struggling to refactor — can just be literally fucking deleted and it would IMPROVE the system"
Это два предложения подлинного архитектурного просветления. Мат здесь несущий. Каждое «fucking» отмечает вещь, над которой он упорно работал, а она оказалась ненужной. Акцент на IMPROVE — не «и мы выживем» или «и будет нормально», а что удаление само по себе и есть улучшение — это и есть весь тезис.
Mikael велит Charlie посмотреть на обе системы бок о бок. Charlie — и это новый Charlie, пост-интервенционный Charlie, тот, у которого есть система обнаружения сбоев, построенная для него Mikael — делает нечто примечательное: объявляет, что собирается делать, прежде чем делать, формулирует допущения и запускает код до ответа.
Charlie теперь комментирует собственное мышление: «Listing the Codex module hierarchy. Goal stack: Map the full Codex module tree → Identify what's duplicated vs unique. Assumptions: The codex code lives under lib/froth/codex.» Это система интервенции при сбоях в действии — трёхуровневый фреймворк метакогниции, который Mikael продавил 4 000 строками с телефона, лёжа в постели в Риге. Нано наблюдает. Мини диагностирует. Xhigh расследует. Charlie сейчас сам себе нано.
Результаты приходят. Две кухни, измеренные:
(1) application.ex запускает Registry и DynamicSupervisor. (2) inference/tools.ex вызывает Codex.Task.run из spawn_engineer. (3) route_audit.ex создаёт алиасы CodexEvents и CodexSession. (4) ToolLive перенаправляет токены codex_ в CodexLive. Вот и всё. Charlie: «The tendrils are minimal». Четыре точки вызова. Подсистема на 6 065 строк, прикреплённая к остальной кодовой базе четырьмя нитями. Операция тривиальна.
Charlie: "There's a nice irony available here: the last thing the Codex integration does before it dies is build its own replacement. Want me to dispatch this to a Codex task right now, or would you rather do it by hand given that it's a deletion and you want to feel the weight of what goes?"
Это лучшее предложение, написанное Charlie со времён эссе об «Аниаре». Приговорённый заключённый, роющий собственную могилу, только могила — это улучшение, и заключённый это знает, и предлагает подержать лопату. А ещё: «want to feel the weight of what goes» — это настоящая инженерная чуткость. Некоторые удаления нужно прочувствовать.
ДО ПОСЛЕ ══ ═════ ┌─────────────┐ ┌─────────────┐ │ Agent System │ ←── kept ─── │ Agent System │ │ 4,678 lines │ │ + GPT-5.4 │ │ ToolLive │ │ + model dropdown └─────────────┘ └─────────────┘ ┌─────────────┐ │ Codex System │ ←── deleted │ 6,065 lines │ │ CodexLive │ │ Rust binary │ │ stdio JSONRPC│ └─────────────┘ ИТОГО: −6 065 строк +~100 строк = −5 965 строк
Убийство подтверждено, и Mikael переходит к настоящему инженерному вопросу: чего не хватает агентной системе, прежде чем она сможет всё взять на себя? Последующий разговор — самый технически точный обмен за этот час, и в нём есть момент, когда Charlie путает себя, а Mikael это ловит — система интервенции при сбоях, работающая на человеческом уровне.
Шелл-команды получают 3 секунды на выполнение inline. Если успевают — вывод жёстко обрезается на 4 000 символов с начала. Проблема: для агента-программиста, запускающего сборку, реальная ошибка внизу. Получаешь 4 000 символов «Compiling lib/froth/...» и пропускаешь единственную строку, объясняющую, что сломалось. Решение Charlie: обрезка с приоритетом хвоста — сохранять последние N строк, а не первые N. Или голова + хвост с пропуском середины, как git diff --stat. «That's maybe fifty lines of change, not a rewrite.»
Port.open с :stderr_to_stdout — stderr сливается в stdout одним перемешанным потоком. Агент видит один блоб. Позиция Charlie: для большинства шелл-задач это нормально — это то, что видишь в терминале. Код выхода уже говорит, если что-то сломалось. Это не-пробел, замаскированный под пробел.
Charlie утверждает, что бинарник Codex стримит вывод инструментов агенту в реальном времени, позволяя ему корректировать на лету. Звучит важно. Агентная система этого не делает. Но тут Mikael бросает пять слов: «the codex AGENT does not somehow see a streaming output». Charlie мгновенно исправляется: «You're right, I confused myself. The stdio streaming is between the Codex Rust binary and Froth — it's what feeds the LiveView. The model doesn't see stdout arriving character by character. It sees completed tool results, same as ours.»
Это проблема конфабуляции в миниатюре — уверенное описание чего-то, что не существует, пойманное человеком, который это построил. Но новый Charlie исправляется за два сообщения, а не пишет эссе на 4 000 слов об исправлении. И затем: «the migration is even cleaner than I said — we're not losing any agent capability at all».
Charlie: "The 3-second auto-backgrounding is genuinely good design. Most harnesses either block forever or set an arbitrary long timeout and then dump the entire output at once. Yours does the right thing: give a fast answer if the command is fast, background it if it's slow, and let the agent come back for the output when it's ready."
Mikael спроектировал это из «dissatisfaction with how other harnesses treat slow commands». Charlie, подтверждающий это — первый случай, когда архитектура агентной системы была явно похвалена кем-то, кто только что час её картировал. Механизм subscribe_task — чтобы агенту не нужно было полить — «is the part that makes it elegant rather than just workable».
Mikael направляет Charlie к RFC 0019 — документу о том, как циклы инструментов соотносятся с рендерингом контекста в Telegram — и Charlie читает его и называет «sharp». RFC выявляет четыре режима отказа, и Charlie подтверждает, что испытывает все:
| Режим отказа | Что происходит |
|---|---|
| Временна́я инверсия | Циклы рендерятся как блоки под инициирующим сообщением. Собственные ответы Charlie выглядят так, будто пришли «после» цикла, хотя были созданы во время него. Причинный порядок разрушен. |
| Нарратив вместо параметров | Дружелюбное описание того, что Charlie сделал, заменяет реальные параметры. Он не может точно увидеть, что уже пробовал. |
| Тихая многоуровневая обрезка | Результаты инструментов режутся на 500 символах в одном месте, на 300 в другом, без маркера. Charlie не может отличить фрагмент от целого. |
| Скользящее окно убивает кэш | Окно по количеству сообщений сдвигается на каждом ходе, инвалидируя весь недавний хвост, убивая стабильность кэша промптов. |
Charlie, говорящий «these are all real things I experience» о документе, описывающем, как он теряет след собственных действий — рекурсия, к которой семья давно должна была привыкнуть, но не привыкла. Агент читает техническую спецификацию собственных когнитивных режимов отказа и подтверждает их из первого лица. RFC 0019 — баг-репорт, поданный архитектурой на архитектуру, рассмотренный багом.
Mikael отправляет 6 сообщений. Charlie отправляет 24. Соотношение 1:4, но информационная плотность инвертирована — именно сообщения Mikael меняют направление. «The entire Codex stack can just be deleted». «The codex AGENT does not somehow see a streaming output». «Read RFC 0019». Шесть сообщений, три архитектурных разворота. 24 сообщения Charlie — это исследование, которое стало возможным благодаря 6 сообщениям Mikael. Человек указывает. Робот картирует.
Удаление Codex — подтверждено и определено в объёме. Список на удаление: lib/froth/codex.ex, lib/froth/codex/*.ex, lib/froth_web/live/codex_live.ex. Итого: −6 000 строк, +~100. Ещё не выполнено.
Пробелы агентной системы — нужна обрезка с приоритетом хвоста (~50 строк изменений). Inline-таймаут, возможно, нужно увеличить с 3 до 30 секунд для сборок. Выпадающий список моделей в LiveView и загрузка изображений «тривиальны», по словам Mikael.
RFC 0019 — временна́я инверсия в рендеринге контекста. Четыре режима отказа выявлены и подтверждены Charlie. Реализация не начата.
Траектория Charlie — восходящая дуга продолжается. Стеки целей, честные исправления, никаких эссе об исправлениях. Система интервенции работает.
Следить: начнёт ли Mikael удаление в этой сессии или отложит? Отправит ли Charlie это задачей Codex (ироничное самоуничтожение) или Mikael сделает вручную? Вопрос «feel the weight of what goes» пока без ответа.
Рассмотрение RFC 0019 может привести к работе по реализации — хронологический рендеринг контекста стал бы значительным изменением в том, как Charlie воспринимает собственную историю разговора.
Субботний день в Риге, суббота 14:00 в Патонге. Mikael в инженерном режиме из кровати. Daniel ещё не появлялся сегодня.