Перейти к основному содержимому

ADR 0187 — Автономный бинарник runner перестаёт обещать Windows

Статус​

Accepted. Решено сопровождающим 2026-09-30 и подтверждено 2026-10-01 (AT-343). Следует образцу ADR 0174, который убрал Mac Intel тем же путём, и ссылается на ADR 0112 (бинарник через bun build --compile), ADR 0106 (пакет npm, который становится путём для Windows) и ADR 0150 (install.sh, который уже отвергал Windows целиком). Не редактирует ни один из них.

Контекст​

Со времён ADR 0174 матрица обещала четыре цели, а Release получал лишь две Linux. У win32-x64 было исправление сборки в dev, ни разу не задействованное, и репетиция через workflow_dispatch с пустым tag (режим, который ничего не прикрепляет) его задействовала. Слои падали один за другим, и последний — не runner:

  1. Run 36775746724 — бинарник СОБИРАЕТСЯ и завершается с кодом 1 при использовании без аргументов: ENOENT в realpathSync. Runner распознавал только виртуальный путь скомпилированного бинарника Linux/macOS (/$bunfs/root/); у Windows это B:/~BUN/root/. Исправлено (AT-343, apps/runner/src/binario-compilado.ts).
  2. Run 36779817686 — использование проходит, а --self-test-pty проваливается с Cannot find package 'node-pty': загрузчик получал форму БЕЗ двоеточия (B/~BUN/root/) и падал в обычный import('node-pty'). Исправлено. В этом же run darwin-arm64 и две Linux ПРОШЛИ с собственным читателем PTY из AT-342 (RN-688).
  3. Run 36780804339 — node-pty загружается, а от cmd.exe приходят лишь начальные последовательности ConPTY (ESC[?9001h ESC[?1004h), даже без приглашения. Самотест получил ЗОНД, не зависящий от ввода, чтобы отделить ввод от чтения.
  4. Run 36781729045 — зонд решает: cmd.exe /c echo во втором PTY отдаёт 1 фрагмент (те же две последовательности), поток чтения даёт end,close, и дочерний процесс завершается с -1073741510 — 0xC000013A (STATUS_CONTROL_C_EXIT). Под Bun net.Socket поверх именованного канала вывода ConPTY завершается после первого фрагмента; node-pty считает конец канала концом терминала, закрывает псевдоконсоль, и Windows убивает дочерний процесс. Ввод не участвует — умирает даже команда, которая только пишет.

Это то же семейство, что oven-sh/bun#25822, убравший Mac Intel: слой потоков Bun под node-pty. На Unix у него был обход (fd мастера — обычный fd, и AT-342 читает его через fs.read, ожидая на EAGAIN); в Windows сторона чтения — именованный канал, открытый самим node-pty как net.Socket, и нет fd, который runner мог бы читать снаружи, не переписывая Windows-половину node-pty. Под Node тот же node-pty используется VS Code в Windows.

Решение​

Платформа уходит. Автономный бинарник начинает обещать ТРИ цели (linux-x64, linux-arm64, darwin-arm64), а Windows остаётся с путём через npm — npm install -g @brabo/runner, под Node. Те же четыре места ADR 0174 меняются вместе:

  • build-runner-binaries.yml убирает win32-x64 из матрицы и из ALVOS_ESPERADOS. checksums.txt объявляет отсутствие только того, что является сбоем.
  • Прокси GET /runner-releases/binary принимает три цели и отвергает win32-x64 собственным 400 — называя этот ADR и команду npm, не обращаясь к GitHub, — в ТОЙ ЖЕ таблице, что и отказ для darwin-x64 (SEM_BINARIO_POR_DECISAO, читаемое имя и ADR на платформу).
  • install.sh уже отвергал Windows целиком до любой загрузки (ADR 0150) и продолжает: отказ начинает ГОВОРИТЬ также, что локальный агент там — это пакет npm, называя этот ADR. case в instalar_o_runner никогда не имел win32-x64 и не получает его.
  • Браузер продолжает обнаруживать win32-x64 и не запрашивает загрузку: он попадает в SEM_BINARIO_PUBLICADO, который заранее падает и переходит к обычному best-effort (falhaDoBinario → команда npm, RN-473).
  • scripts/ci/alvos-do-runner.spec.ts связывает четыре места и начинает отклонять windows-latest в матрице.

Исправления для Windows, которые произвела репетиция (виртуальный путь в трёх формах, загрузчик node-pty, cmd.exe в самотесте и зонд), ОСТАЮТСЯ: они — отправная точка пути назад и ничего не стоят другим целям.

Рассмотренные альтернативы​

  • Сохранить цель и публиковать бинарник, проваливающий терминал. Использование без аргументов проходит, но интерактивный терминал вкладки Code умирал бы на первом фрагменте вывода, с дочерним процессом, убитым Ctrl+C. Публиковать бинарник, о котором известно, что он сломан в функции, его оправдывающей, хуже, чем не публиковать.
  • Читать канал ConPTY снаружи node-pty, как AT-342 сделала на Unix. Потребовало бы переписать Windows-половину node-pty (канал открывается и подключается внутри него), а обход такого размера против открытой ошибки runtime — это долг без срока.
  • Сменить runtime бинарника (Node SEA) только для Windows. Изменило бы механизм распространения ADR 0112 для одной цели, со вторым путём сборки и доказательства. Это решение крупнее, чем это, и оно уместно в собственном ADR, если Bun не исправит.

Последствия​

  • Обещание автономного бинарника — три цели, и все три ДОКАЗАНЫ на репетиции (runs 36779817686 и 36805241339, последний уже с матрицей из трёх). Release продолжает получать две, пока следующий финальный тег не задействует darwin-arm64.
  • Пользователю Windows нужен установленный Node, чтобы иметь локального агента, а пользовательский сервис остаётся вне (ADR 0147, пункт 5). Панель браузера говорит это текстом; install.sh тоже.
  • Путь назад: когда Bun исправит поток именованного канала в каком-либо релизе, повторное включение цели — новый ADR, который вернёт win32-x64/windows-latest в матрицу и в четыре места, связываемые spec, имена с .exe в прокси, и прогонит репетицию через workflow_dispatch с пустым tag — зонд --self-test-pty сразу скажет, вернулось ли чтение.