Forge Mobile Dev Station

Путь: /home/claude/forge/ Сервис: forge.service (systemd —user), порт 3000 (fastify + ws), процесс bot.js Стек: fastify, better-sqlite3 (forge.db), telegraf (Telegram-бот), ws (WebSocketServer), Vite miniapp (miniapp/)

Отдельный проект от claudeclawclaudeclaw свой модуль src/forge.ts для управления тасками — не путать с этим сервисом).

Архитектура

  • bot.js — Telegram-бот, точка входа, спавнит Claude Code сессии на задачи
  • server.js — HTTP API (/api/tasks*, /api/projects) + WS-сервер на том же порту 3000
  • supervisor.jsbuildPlan / executeTask / killTask / mergeAndClean (PLAN-GATE workflow)
  • db.js + forge.db — sqlite, таблицы tasks, forge_events
  • events.js — EventEmitter, мост между supervisor-событиями и WS-рассылкой
  • miniapp/ — Telegram Mini App (Vite), фронтенд для просмотра задач

WebSocket endpoint

ws://<host>:3000/ws/tasks/:id — по одному подключению на задачу.

  • При коннекте сервер сразу шлёт {type:'init', events:[...], status:...} (вся история событий таска)
  • Далее пушит новые события через taskEvents.on('task:<id>', ...)status_change и т.п.
  • Входящие сообщения от клиента не обрабатываютсяws.on('message', ...) в server.js не зарегистрирован. Это read-only канал сервер→клиент.
  • Нет пути path фильтра на уровне WebSocketServer — роутинг вручную через regex на req.url

Тест WS (2026-07-01)

Тестировали на живой задаче id=34 (“WS test task” — эта же сессия себя тестировала).

Результат:

  • ✅ Подключение к ws://127.0.0.1:3000/ws/tasks/34 — успешно, init с историей событий пришёл сразу
  • ✅ Отправка сообщения клиент→сервер — принята без ошибок (сервер её просто игнорирует, ожидаемо — обработчика нет)
  • ✅ Разрыв соединения (close(1000)) и повторное подключение — переподключение работает, init снова приходит корректно
  • ⚠️ Логов нет вообще: fastify({logger:false}), WS-подключения/отключения/ошибки нигде не пишутся в journalctl. Если WS сломается в проде — узнать об этом можно будет только по симптомам в miniapp, не по логам
  • ⚠️ Ненормальный shutdown: при каждом рестарте forge.service виден stop-sigterm timed outSIGKILL (см. journalctl --user -u forge.service). Это значит открытые WS-соединения рвутся без close-фрейма (клиент получит 1006, а не штатный 1000/1005). Стоит разобраться, что в bot.js/server.js блокирует грациозный шатдаун (скорее всего висящий Claude Code child process в supervisor).

Незакрытые задачи

  • Добавить логирование WS-событий (connect/disconnect/error) хотя бы на logger: true или явный console.log
  • Разобраться с graceful shutdown — что не даёт процессу завершиться по SIGTERM за 90 сек