Kanban — Коллаборация нескольких профилей

Хотите пошаговое руководство? Прочитайте Учебник по канбану — четыре пользовательские истории (одиночная разработка, флотская ферма, конвейер ролей с повторными попытками, автоматический выключатель) со скриншотами панели управления для каждой. Эта страница — справочная; учебник — повествование.

Hermes Kanban — это долговечная доска задач, общая для всех ваших профилей Hermes, которая позволяет нескольким именованным агентам совместно работать без хрупких внутрипроцессных роёв подагентов. Каждая задача — это строка в ~/.hermes/kanban.db; каждая передача — это строка, которую любой может прочитать и записать; каждый воркер — это полноценный процесс ОС со своей собственной идентичностью.

Два интерфейса: модель общается через инструменты, вы — через CLI

У доски два входа, оба поддерживаются одной и той же ~/.hermes/kanban.db:

Оба интерфейса проходят через один и тот же слой kanban_db, поэтому чтения видят согласованное представление, а записи не могут расходиться. Остальная часть этой страницы показывает примеры CLI, потому что их легко копировать и вставлять, но каждый глагол CLI имеет эквивалентный вызов инструмента, который использует модель.

Это форма, которая покрывает рабочие нагрузки, с которыми delegate_task не справляется:

Полное обоснование дизайна, сравнительный анализ с Cline Kanban / Paperclip / NanoClaw / Google Gemini Enterprise и восемь канонических шаблонов коллаборации см. в docs/hermes-kanban-v1-spec.pdf в репозитории.

Kanban vs. delegate_task

Они выглядят похожими; это не один и тот же примитив.

delegate_task Kanban
Форма RPC-вызов (fork → join) Долговечная очередь сообщений + конечный автомат
Родитель Блокируется, пока дочерний не вернётся Забыл и пошёл дальше после create
Идентичность дочернего Анонимный подагент Именованный профиль с постоянной памятью
Возобновляемость Нет — не удалось = не удалось Блокировка → разблокировка → повторный запуск; сбой → отзыв
Человек в цикле Не поддерживается Комментарий / разблокировка в любой момент
Агентов на задачу Один вызов = один подагент N агентов за время жизни задачи (повтор, ревью, последующие действия)
Аудиторский след Потерян при сжатии контекста Долговечные строки в SQLite навсегда
Координация Иерархическая (вызывающий → вызываемый) Одноранговая — любой профиль читает/пишет любую задачу

Различие в одном предложении: delegate_task — это вызов функции; Kanban — это очередь работ, где каждая передача — это строка, которую любой профиль (или человек) может видеть и редактировать.

Используйте delegate_task, когда родительскому агенту нужен короткий ответ на рассуждение перед продолжением, без участия людей, результат возвращается в контекст родителя.

Используйте Kanban, когда работа пересекает границы агентов, должна пережить перезапуски, может потребовать ввода от человека, может быть подхвачена другой ролью или должна быть обнаружима после факта.

Они сосуществуют: канбан-воркер может внутренне вызывать delegate_task во время своего запуска.

Основные понятия

Доски (мультипроект)

Доски позволяют разделять несвязанные потоки работы — по одному на проект, репозиторий или домен — в изолированные очереди. Новая установка имеет ровно одну доску с именем default (БД в ~/.hermes/kanban.db для обратной совместимости). Пользователи, которым нужен только один поток работы, никогда не должны знать о досках; функция опциональна.

Изоляция между досками абсолютна:

Управление досками из CLI

# Посмотреть, что есть на диске. Свежие установки показывают только "default".
hermes kanban boards list

# Создать новую доску.
hermes kanban boards create atm10-server \
    --name "ATM10 Server" \
    --description "Операции модового сервера Minecraft" \
    --icon 🎮 \
    --switch                   # опционально: сделать активной доской

# Работать с конкретной доской без переключения.
hermes kanban --board atm10-server list
hermes kanban --board atm10-server create "Перезапустить ATM сервер" --assignee ops

# Изменить, какая доска является "текущей" для последующих вызовов.
hermes kanban boards switch atm10-server
hermes kanban boards show             # кто активен сейчас?

# Переименовать отображаемое имя (слаг неизменяем — это имя каталога).
hermes kanban boards rename atm10-server "ATM10 (Prod)"

# Архивировать (по умолчанию) — перемещает каталог доски в boards/_archived/<slug>-<ts>/.
# Восстановимо путём перемещения каталога обратно.
hermes kanban boards rm atm10-server

# Жёсткое удаление — `rm -rf` каталога доски. Без восстановления.
hermes kanban boards rm atm10-server --delete

Порядок разрешения доски (наивысший приоритет первый):

  1. Явный --board <slug> в вызове CLI.
  2. Переменная окружения HERMES_KANBAN_BOARD (устанавливается диспетчером при запуске воркера, поэтому воркеры не могут видеть другие доски).
  3. ~/.hermes/kanban/current — слаг, сохранённый командой hermes kanban boards switch.
  4. «по умолчанию».

Слаги проверяются: строчные буквы, цифры, дефисы и подчёркивания, символы 1–64, должны начинаться с букв или цифр. Ввод в верхнем регистре автоматически приведет к записи. Всё остальное (слеши, пробелы, точки, ..) отклоняется на уровне CLI, чтобы трюки с обходом пути не могли назвать доску.

Управление досками из панели управления

приборная панель Hermesа → вкладка Канбан показывает переключатель досок вверх, как только появляется более одной доски (или любая доска имеет задачу). Однодосочные пользователи поддерживают только кнопку + Новая доска; Переключатель скрыт, пока не понадобится.

Все конечные точки API панели управления принимают ?board=<slug> для дополнительных ограничений. События WebSocket выносятся на доске при подключении; переключение в UI открывает новый WS для новой доски.

Быстрый старт

Команды ниже — это вы (человек), настраивающий доску и создающий задачи. Как только задача назначена, диспетчер запускает назначенный профиль как воркера, и с этого момента модель управления подключается через вызовы инструментов kanban_*, а не по команде CLI — см. Как воркеры взаимодействуют с доской.

# 1. Создать доску (вы)
hermes kanban init

# 2. Запустить шлюз (содержит встроенный диспетчер)
hermes gateway start

# 3. Создать задачу (вы — или агент-оркестратор через kanban_create)
hermes kanban create "исследовать ландшафт финансирования AI" --assignee researcher

# 4. Наблюдать за активностью в реальном времени (вы)
hermes kanban watch

# 5. Посмотреть доску (вы)
hermes kanban list
hermes kanban stats

Когда диспетчер подхватывает t_abcd и запускает профиль researcher, первое, что делает модель этого воркера, — вызывает kanban_show(), чтобы прочитать свою задачу. Она не запускает hermes kanban show t_abcd.

Диспетчер, встроенный в шлюз (по умолчанию)

Диспетчер работает внутри шлюза процесса. Ничего хранить не нужно, не нужно управлять поворотным сервисом — если шлюз работает, готовые задачи подхватываются в следующий раз (60 с по умолчанию).

# config.yaml
kanban:
  dispatch_in_gateway: true        # по умолчанию
  dispatch_interval_seconds: 60    # по умолчанию

Переопределите флаг конфигурации во время выполнения через HERMES_KANBAN_DISPATCH_IN_GATEWAY=0 для отладки. Применяется стандартное наблюдение за шлюзом: запустите запуск шлюза Hermes напрямую или подключите шлюз как пользовательский системный модуль (см. документация шлюза). Без работающего шлюза задача в статусе готово остаётся на месте, пока он не появится — hermes kanban create предупреждает об этом при создании.

Запуск hermes kanban daemon как отдельного процесса устарел; воспользуйтесь шлюзом. Если вы действительно не можете запустить шлюз (политика безголового хоста запрещает долгоживущие сервисы и т.д.), запасной вариант --force сохраняет старый автономный демон в одном цикле релиза, но запуск встроенного в диспетчера шлюза, ТАК и автономного демона против одного и тот же kanban.db не вызывает скачков захвата и не вызывает.

Идемпотентное создание (для автоматизации/вебхуков)

# Первый вызов создаёт задачу. Любой последующий вызов с тем же ключом
# возвращает существующий id задачи вместо дублирования.
hermes kanban create "ночной обзор операций" \
    --assignee ops \
    --idempotency-key "nightly-ops-$(date -u +%Y-%m-%d)" \
    --json

Массовые глаголы CLI

Все глаголы жизненного цикла принимают несколько идентификаторов, чтобы вы могли использовать горячий пакет одной команды:

hermes kanban complete t_abc t_def t_hij --result "пакетное завершение"
hermes kanban archive  t_abc t_def t_hij
hermes kanban unblock  t_abc t_def
hermes kanban block    t_abc "нужен ввод" --ids t_def t_hij

Как рабочие взаимодействуют с доской

Воркеры не вызывают hermes kanban через обёртку. Когда диспетчер запускает воркера, он устанавливает HERMES_KANBAN_TASK=t_abcd в ходе дочернего процесса, и эта переменная окружность включает выделенный набор инструментов канбан в шаблоне модели. Тот же набор инструментов также доступен в профилях оркестраторов, включая «канбан» в конфигурации своих наборов инструментов. Эти инструменты читают и изменяют документы напрямую через слой Python kanban_db, так же, как и CLI. Работающий воркер предлагает их как любые другие инструменты; он никогда не видит и не нуждается в CLI hermes kanban.

Инструмент Назначение Обязательные параметры
kanban_show Прочитать текущую задачу (заголовок, тело, предложение, передача от родителей, комментарии, полностью предварительно отформатированный worker_context). По умолчанию используются идентификаторы задач из окружения.
kanban_list Список сводок задач с фильтрами по правопреемнику, статусу, арендатору, боковым архивированным и лимиту. определения для оркестраторов, находящих работу на доске.
kanban_complete Завершить с сводкой + метаданными структуры передачи. хотя бы один из сводки / результата
kanban_block Эскалировать для ввода человеком «причину». причина
kanban_heartbeat Сигнал активности во время длительных операций. Чистый побочный эффект.
kanban_comment Добавьте разверточную заметку в цепочку задач. task_id, тело
kanban_create (Оркестраторы) разветвиться на дочерние задачи с правопреемником, опциональными родителями, навыками и т.д. титул, правопреемник
kanban_link (Оркестраторы) добавляют ребро в зависимости parent_id → child_id по факту. parent_id, child_id
kanban_unblock (Оркестраторы) переместить заблокированную задачу обратно в состояние готово. task_id

Типичный шаг воркера выглядит так:

# Вызовы инструментов модели, по порядку:
kanban_show()                                     # без аргументов  использует HERMES_KANBAN_TASK
# (модель читает возвращённый worker_context, выполняет работу через инструменты terminal/file)
kanban_heartbeat(note="на полпути — 4 из 8 файлов преобразованы")
# (ещё работа)
kanban_complete(
    summary="мигрировал limiter.py на token-bucket; добавил 14 тестов, все проходят",
    metadata={"changed_files": ["limiter.py", "tests/test_limiter.py"], "tests_run": 14},
)

Оркестратор вместо этого разветвления:

kanban_show()
kanban_create(
    title="исследовать финансирование ICP 2024-2026",
    assignee="researcher-a",
    body="сосредоточиться на seed + series A, Северная Америка, смежные с AI",
)
#  возвращает {"task_id": "t_r1",...}
kanban_create(title="исследовать финансирование ICP — угол EU", assignee="researcher-b", body="…")
#  возвращает {"task_id": "t_r2",...}
kanban_create(
    title="синтезировать результаты в краткий обзор для запуска",
    assignee="writer",
    parents=["t_r1", "t_r2"],                     # продвигается в ready, когда оба завершены
    body="одностраничник, 300 слов, нейтральный тон",
)
kanban_complete(summary="декомпозировал на 2 исследовательские задачи + 1 писатель; связал зависимости")

Инструменты "(Оркестраторы)" — kanban_list, kanban_create, kanban_link, kanban_unblock и kanban_comment для чужих задач — доступны через тот же набор инструментов; Соглашение (подкреплённое навыком «канбан-оркестратор») заключается в том, что профили рабочих не разветвляются и не направляют несвязанную работу, а профили оркестраторов не выполняют реализационную работу. Работники, активированные диспетчером, по-прежнему ограничены в размерах для деструктивных операций жизненного цикла и не могут изменять несвязанные задачи.

Почему инструменты вместо вызова hermes kanban через обёртку

Три причины:

  1. Переносимость бэкенда. Воркеры, чей инструмент терминала указывает на удалённый бэкенд (Docker/Modal/Singularity/SSH), запускали бы hermes kanban Complete внутри контейнера, где hermes не установлен и ~/.hermes/kanban.db не смонтирован. Инструменты канбаны работают в собственном агенте Python-процесса и всегда используются ~/.hermes/kanban.db независимо от серверного терминала.
  2. Нет хрупкости с кавычками обработки. Передача --metadata '{"files": [...]}' через shlex + argparse — это открытая грабля. Структурированные аргументы инструмента полностью ее избегают.
  3. Лучшие ошибки. Инструменты результатов — это структурированный JSON, о котором модель может рассуждать, а не строки stderr, которые ей нужно парсить.

Новая схема следования в обычных сессиях. Обычная сессия hermeschat имеет ноль инструментов kanban_* в своей схеме. check_fn каждый инструмент возвращает True только тогда, когда установлен HERMES_KANBAN_TASK, что происходит только тогда, когда диспетчер запустил этот процесс. Никакого раздувания инструментов для пользователей, которые никогда не касаются канбаны.

Навыки kanban-worker и kanban-orchestrator обучают модели, какой инструмент работает, когда и в каком порядке.

Рекомендуемые документы передачи

kanban_complete(summary=..., метаданные={...}) намеренно гибок: summary — это человекочитаемое закрытие, а метаданные — это машиночитаемая передача, которую нижестоящие агенты, ревьюеры или панели управления могут использовать без извлечения из прозы.

Для инженерных задач и задач обзора предпочтительна следующая опциональная форма метаданных:

{
  "changed_files": ["path/to/file.py"],
  "verification": ["pytest tests/hermes_cli/test_kanban_db.py -q"],
  "dependencies": ["id родительской задачи или внешний issue, если есть"],
  "blocked_reason": null,
  "retry_notes": "что не удалось раньше, если это был повтор",
  "residual_risk": ["что не было протестировано или всё ещё требует человеческого ревью"]
}

Эти ключи — соглашение, а не схема требований. Полезное свойство в том, что каждый воркер оставляет достаточно доказательств, чтобы следующий читатель мог быстро ответить на четыре вопроса:

  1. Что изменилось?
  2. Как это было проверено?
  3. Что может разблокировать или отобразить это, если оно не спасет?
  4. Какой риск всё ещё намеренно оставлено открытым?

Храните секреты, сырые логи, токены, OAuth-материалы и несвязанные транскрипты вне «метаданных». Вместо этого сохраните указатели и сводки. Если у вас нет файлов или тестов, укажите это явно в «сводке» и воспользуйтесь «метаданными» для тех доказательств, которые существуют, таких как источники URL, проблемы с идентификаторами или этапы ручного обзора.

Навык воркера

Любой профиль, который должен уметь работать с задачами канбана, должен загрузить навыки «канбан-работник». Он обучает работу полного жизненного цикла в вызовах инструментов, а не в команде CLI:

  1. При запуске вызываете kanban_show(), чтобы прочитать заголовок + тело + передачу от родителей + сообщение о процедуре + полную цепочку комментариев.
  2. cd $HERMES_KANBAN_WORKSPACE (через инструмент терминала) и выполните работу там.
  3. Вызывать kanban_heartbeat(note="...") несколько минут во время длительных операций.
  4. Завершить с помощью kanban_complete(summary="...", Metadata={...}) или kanban_block(reason="..."), если застряли.

kanban-worker — это встроенный навык, синхронизируемый в каждом профиле во время установки и обновления — нет отдельного шага установки из Skills Hub. Проверьте его наличие в том профиле, который вы используете для канбан-воркеров («исследователь», «писатель», «опс» и т.д.):

hermes -p <your-worker-profile> skills list | grep kanban-worker

Если встроенная копия отсутствует, восстановите ее для этого профиля:

hermes -p <your-worker-profile> skills reset kanban-worker --restore

Диспетчер также автоматически передаёт --skills kanban-worker при запуске каждого воркера, поэтому воркер всегда имеет встроенные шаблоны, даже если настройки профиля функций по умолчанию не включают его.

Прикрепление дополнительных функций к конкретной задаче

Иногда одной задаче нужен специализированный контекст, профиль которого не несёт по умолчанию — задача перевода, необходимые навыки перевода, задача ревью, требующая github-code-review, аудит безопасности, требующий security-pr-audit. Вместо изменения назначения профиля каждый раз прикрепляйте навыки непосредственно к задаче.

От агента-оркестратора (обычный случай — один агент направляет работу в течение раунда), воспользуйтесь инструментом kanban_create массива skills:

kanban_create(
    title="перевести README на японский",
    assignee="linguist",
    skills=["translation"],
)

kanban_create(
    title="аудит потока аутентификации",
    assignee="reviewer",
    skills=["security-pr-audit", "github-code-review"],
)

От человека (CLI/слэш-команда), повторите --skill для каждого:

hermes kanban create "перевести README на японский" \
    --assignee linguist \
    --skill translation

hermes kanban create "аудит потока аутентификации" \
    --assignee reviewer \
    --skill security-pr-audit \
    --skill github-code-review

Из панели управления введите навыки через запятую в поле skills создание встроенной формы.

Эти навыки добавляются к встроенному kanban-worker — диспетчер выдаёт один флаг --skills <name> для каждого (и для встроенного), поэтому воркер запускается со всеми загруженными. Имена функций должны соответствовать навыкам, которые установлены в профиле назначения (запустите «Список навыков Hermesа», чтобы увидеть доступные); установка во время выполнения не производилась.

Навык оркестратора

Хорошо воспитанный оркестратор не делает работу сам. Он декомпозирует цели пользователя для задач, связывает их, включает каждого из настроенных профилей и выходит. Навык kanban-orchestrator кодирует это как инструменты шаблонов вызовов: правила против соблазна, подсказка для поиска профилей на шаге 0 (диспетчер молчат о неудачах в неизвестных именах, поэтому оркестратор должен обосновывать каждую карту профилями, которые действительно существуют на вашей машине), и декомпозиции плейбука, основанные на kanban_create / kanban_link / kanban_comment.

Канонический шаг оркестратора (два параллельных исследователя передают работу писателю):

# Цель от пользователя: "написать пост о запуске на тему ландшафта финансирования ICP"
kanban_create(title="исследовать финансирование ICP, угол NA",  assignee="researcher-a", body="…")  #  t_r1
kanban_create(title="исследовать финансирование ICP, угол EU",  assignee="researcher-b", body="…")  #  t_r2
kanban_create(
    title="синтезировать исследование финансирования ICP в черновик поста о запуске",
    assignee="writer",
    parents=["t_r1", "t_r2"],        # продвигается в 'ready', когда оба исследователя завершат
    body="одностраничник, нейтральный тон, цитировать источники в тексте",
)                                     #  t_w1
# Опционально: добавить сквозные зависимости, обнаруженные позже, без пересоздания задач
kanban_link(parent_id="t_r1", child_id="t_followup")
kanban_complete(
    summary="декомпозировал на 2 параллельные исследовательские задачи → 1 задача синтеза; писатель начинает, когда оба исследователя заканчивают",
)

«Канбан-оркестратор» — это встроенный навык. Он синхронизируется с каждым профилем во время установки и обновления, поэтому нет отдельного шага установки из Skills Hub. проверьте его наличие в вашем профиле оркестратора:

hermes -p orchestrator skills list | grep kanban-orchestrator

Если встроенная копия отсутствует, восстановите ее для этого профиля:

hermes -p orchestrator skills reset kanban-orchestrator --restore

Для достижения наилучших результатов скомбинируйте его с профилем, его наборы инструментов ограничены операциями с доской («канбан», «шлюз», «память»), чтобы оркестратор буквально не мог выполнить задачу реализации, даже если будет попытка.

Панель управления (GUI)

CLI /kanban и слэш-команда достаточны для безголового управления доской, но визуальная доска часто является интерфейсом для людей в цикле: триаж, межпрофильное наблюдение, чтение цепочек комментариев и перетаскивание карточек между колонками. Hermes представляет собой встроенный плагин панели управления в plugins/kanban/ — не основная функция, не отдельный сервис — следующая модель, изложенная в Расширение панели управления.

Откройте его с помощью:

hermes kanban init      # однократно: создать kanban.db, если ещё не существует
hermes dashboard        # вкладка "Kanban" появляется в навигации, после "Skills"

Что даёт плагин

Визуально цель — знакомый макет Linear / Fusion: тёмная тема, заголовки колонок с количеством, цветные точки статуса, чипы-пилюли для приоритета и арендатора. Плагин читает только CSS-переменные темы (--color-*, --radius, --font-mono,...), поэтому он автоматически перекрашивается в соответствии с активной темой панели управления.

Архитектура

GUI — это строго слой чтения-через-БД + записи-через-kanban_db без собственной доменной логики:

┌────────────────────────┐      WebSocket (отслеживает task_events)
│   React SPA (плагин)   │ ◀──────────────────────────────────┐
│   HTML5 drag-and-drop  │                                    │
└──────────┬─────────────┘                                    │
           │ REST через fetchJSON                              │
           ▼                                                  │
┌────────────────────────┐     записи вызывают kanban_db.*     │
│  FastAPI router        │     напрямую — тот же путь кода    │
│  plugins/kanban/       │     который используют CLI /kanban │
│  dashboard/plugin_api.py                                    │
└──────────┬─────────────┘                                    │
           │                                                  │
           ▼                                                  │
┌────────────────────────┐                                    │
│  ~/.hermes/kanban.db   │ ───── добавляет task_events ───────┘
│  (WAL, общая)          │
└────────────────────────┘

REST-поверхность

Все маршруты смонтированы под /api/plugins/kanban/ и защищены эфемерным токеном сессии панели управления:

Метод Путь Назначение
ПОЛУЧИТЬ /board?tenant=<имя>&include_archived=… Полная доска, группы по колонкам, плюс арендаторы + предназначение для выпадающих фильтров
ПОЛУЧИТЬ /задачи/:id Задача + комментарии + события + связь
ПОСТ /задачи Создать (обёртка kanban_db.create_task, принимает triage: bool и parents: [id, …])
ПАТЧ /задачи/:id Статус / назначение / приоритет / заголовок / тело / результат
ПОСТ /tasks/bulk Примените тот же патч (статус/архив/назначение/приоритет) ко всему id в ids. Сбои по каждому идентификатору передаются без прерывания остальных
ПОСТ /задачи/:id/комментарии Добавить комментарий
ПОСТ /tasks/:id/specify Запустить специального специалиста по триаже — вспомогательная LLM по реализации задач по телосложению и продвижению ее из triage в todo. Возвращает {ok, Task_id, причина, new_title}; ok=false с человекочитаемой причиной ("не в триаже" / нет aux-клиента / ошибка LLM) — это 200, а не 4xx
ПОСТ /ссылки Добавить зависимость (parent_idchild_id)
УДАЛИТЬ /links?parent_id=…&child_id=… Удалить зависимость
ПОСТ /dispatch?max=…&dry_run=… Подтолкнуть диспетчера — пропустить ожидание в 60 с
ПОЛУЧИТЬ /конфигурация Прочитать настройки dashboard.kanban из config.yamldefault_tenant, lane_by_profile, include_archived_by_default, render_markdown
ВС /events?since=<event_id> Потоковая строка task_events в первое время

Каждый обработчик — тонкая обёртка — плагин содержит ~700 строк Python (роутер + WebSocket-отслеживание + массовый батчер + читатель конфига) и не добавляет новой бизнес-логики. Крошечный хелпер _conn() автоматически инициализирует kanban.db при каждом чтении и записи, поэтому новая установка независимо работает от того, открыл ли пользователь сначала панель управления, перешёл напрямую к REST API или запустил hermes kanban init.

Конфигурация панели управления

Любой из этих ключей в dashboard.kanban в ~/.hermes/config.yaml изменяет значения по умолчанию для вкладки — плагин читает их при включении через GET /config:

dashboard:
  kanban:
    default_tenant: acme              # предварительно выбирает фильтр арендатора
    lane_by_profile: true             # по умолчанию для переключателя "полосы по профилю"
    include_archived_by_default: false
    render_markdown: true             # установите false для простого рендеринга <pre>

Каждый ключ опционален и возвращается к неожиданному положению производства.

Модель безопасности

Промежуточное ПО HTTP-аутентификации панели управления явно пропускает /api/plugins/ — маршруты плагинов не аутентифицированы по дизайну, потому что панель управления по умолчанию привязывается к localhost. Это означает, что REST-поверхность канбана доступна из любого процесса на хосте.

WebSocket делает еще один дополнительный шаг: он требует эфемерный токен сессии панели управления в качестве параметра запроса ?token=… (браузеры не могут установить Authorization при обновлении запроса), соответствующий шаблону, используемому мостом PTY в браузере.

Если вы запустите «hermes Dashboard --host 0.0.0.0», каждый плагин маршрута — включая канбан — станет доступен из сети. Не делайте это на общем хосте. Доска содержит задачи тела, комментарии и пути к соответствующим пространствам; Злоумышленник, получивший доступ к этим маршрутам, получает доступ для чтения ко всей вашей поверхности совместной работы, а также может создавать/переназначать/архивировать задачу.

Задачи в ~/.hermes/kanban.db намеренно не зависят от профиля (в этом и заключаются примитивные международные соглашения). Если вы откроете панель управления с помощью hermes -p <profile> Dashboard, доска всё равно покажет задачу, созданную любым другим профилем на хосте. Один и тот же пользователь работает со всеми профилями, но об этом стоит знать, если существует несколько человек.

Обновления в последнее время

task_events — эта таблица SQLite только для добавления с монотонным id. Конечная точка WebSocket сохраняет последний просмотренный идентификатор события для каждого клиента и отправляет новые строки по мере их поступления. Когда приходит вспплеск событий, фронтенд перезагружает (очень дешёвую) конечную точку доски — проще и правильнее, чем пытаться исправить локальное состояние из каждого вида событий. Режим WAL означает, что цикл чтения никогда не блокирует транзакцию захвата диспетчера BEGIN IMMEDIATE.

Расширение

Плагин использует стандартный контрактный разъем панели управления Hermes — см. Расширение панели управления для полных ссылок на манифест, слоты обработки, слоты с областью страницы и Plugin SDK. Дополнительные колонки, пользовательское оформление карточек, макеты с фильтрацией по арендатору или полные замены «tab.override» могут быть указаны без вилки этого разъема.

Чтобы отключить без удаления: разделы dashboard.plugins.kanban.enabled: false в config.yaml (или удалите plugins/kanban/dashboard/manifest.json).

Граница области

Графический интерфейс намеренно тонкий. Всё, что делает плагин, доступно из CLI; плагин просто делает это удобным для людей. Автоматическое назначение, бюджеты, шлюзы управления и представление организационной структуры отображаются в пользовательском пространстве — профиль маршрутизатора, другой плагин или повторное использование tools/approval.py — именно так, как указано в разделе «вне области» характеристик дизайна.

Справочник команды CLI

Эта поверхность, которую вы (или скрипты, cron, панель управления) используется для управления доской. Воркеры, работающие внутри диспетчера, используют поверхность инструментов kanban_* для тех же операций — CLI здесь и инструменты там оба передаются через kanban_db, поэтому две поверхности согласованы по построению.

hermes kanban init                                     # создать kanban.db + напечатать подсказку о демоне
hermes kanban create "<title>" [--body...] [--assignee <profile>]
                                [--parent <id>]... [--tenant <name>]
                                [--workspace scratch|worktree|dir:<path>]
                                [--priority N] [--triage] [--idempotency-key KEY]
                                [--max-runtime 30m|2h|1d|<seconds>]
                                [--skill <name>]...
                                [--json]
hermes kanban list [--mine] [--assignee P] [--status S] [--tenant T] [--archived] [--json]
hermes kanban show <id> [--json]
hermes kanban assign <id> <profile>                    # или 'none' для снятия назначения
hermes kanban link <parent_id> <child_id>
hermes kanban unlink <parent_id> <child_id>
hermes kanban claim <id> [--ttl SECONDS]
hermes kanban comment <id> "<text>" [--author NAME]

# Массовые глаголы  принимают несколько id:
hermes kanban complete <id>... [--result "..."]
hermes kanban block <id> "<reason>" [--ids <id>...]
hermes kanban unblock <id>...
hermes kanban archive <id>...

hermes kanban tail <id>                                # следить за потоком событий одной задачи
hermes kanban watch [--assignee P] [--tenant T]        # потоковая передача ВСЕХ событий в терминал
        [--kinds completed,blocked,] [--interval SECS]
hermes kanban heartbeat <id> [--note "..."]            # сигнал живости воркера для длительных операций
hermes kanban runs <id> [--json]                       # история попыток (одна строка на запуск)
hermes kanban assignees [--json]                       # профили на диске + количество задач на назначение
hermes kanban dispatch [--dry-run] [--max N]           # одноразовый проход
        [--failure-limit N] [--json]
hermes kanban daemon --force                           # УСТАРЕЛО  автономный диспетчер (используйте `hermes gateway start`)
        [--failure-limit N] [--pidfile PATH] [-v]
hermes kanban stats [--json]                           # количество по статусу + по назначению
hermes kanban log <id> [--tail BYTES]                  # лог воркера из ~/.hermes/kanban/logs/
hermes kanban notify-subscribe <id>                    # хук моста шлюза (используется /kanban в шлюзе)
        --platform <name> --chat-id <id> [--thread-id <id>] [--user-id <id>]
hermes kanban notify-list [<id>] [--json]
hermes kanban notify-unsubscribe <id>
        --platform <name> --chat-id <id> [--thread-id <id>]
hermes kanban context <id>                             # что видит воркер
hermes kanban specify [<id> | --all] [--tenant T]      # проработать идею из колонки триажа
        [--author NAME] [--json]                       #   в полную спецификацию и продвинуть в todo
hermes kanban gc [--event-retention-days N]            # рабочие пространства + старые события + старые логи
        [--log-retention-days N]

Все также доступно как слэш-команда в интерактивном CLI и в шлюзе обмена сообщениями командами (см. Слэш-команда /kanban ниже).

Слэш-команда /kanban {#слэш-команда-kanban}

Каждый глагол hermes kanban <action> также доступен как /kanban <action> — из интерактивной сессии hermeschat и из любого шлюза платформы (Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Mattermost, электронная почта, SMS). Оба интерфейса вызывают и одну ту же самую точку ввода hermes_cli.kanban.run_slash(), которая повторно использует дерево argparse hermes kanban, поэтому аргументы аргументов, флаги и формат результата в CLI, /kanban и hermes kanban. Вам не нужно выходить из чата, чтобы управлять доской.

/kanban list
/kanban show t_abcd
/kanban create "написать пост о запуске" --assignee writer --parent t_research
/kanban comment t_abcd "выглядит хорошо, отправляй"
/kanban unblock t_abcd
/kanban dispatch --max 3
/kanban specify t_abcd                  # проработать однострочник триажа в реальную спецификацию
/kanban specify --all --tenant engineering  # обработать все задачи триажа в одном арендаторе

Заключайте многословные аргументы в кавычки так же, как в оболочке — run_slash разбирает остаток строки с помощью shlex.split, поэтому работают как "...", так и '...'.

Использование во время выполнения: /kanban обходит защиту работающего агента

Шлюз обычно выдает в свою очередь слэш-команды и сообщения пользователя, пока агент еще мыслей — это свойственный случайный запуск второго шага, пока первый в полёте. /kanban явно освобождён от этой защиты. Доскаёт в ~/.hermes/kanban.db, не в состоянии работающего агента, поэтому чтения (list, show, context, tail, watch, stats, runs) и записи (comment, unblock, block, assign, archive, create, link, …) передать сообщение, даже во время шага.

В этом и заключается весь смысл разделения:

Автоподписка при /kanban create (только в шлюзе)

Когда вы создаёте задачу из шлюза с помощью /kanban create "…", исходный чат (платформа + id чата + id треда) автоматически подписывается на терминальные события этой задачи (completed, blocked, gave_up, crashed, timed_out). Вы возвращаете одно сообщение обратно для каждого терминального события — включая первую запись итогового результата работы при «завершении» — без необходимости запрашивать или запоминать идентификатор задачи.

вы> /kanban create "расшифровать сегодняшний подкаст" --assignee transcriber
бот> Создана t_9fc1a3  (ready, assignee=transcriber)
     (подписан  вы будете уведомлены, когда t_9fc1a3 завершится или заблокируется)

 ~8 минут спустя 

бот>  t_9fc1a3 завершена transcriber
     расшифровано 42 минуты, сохранено в podcast/2026-05-04.md

Подписки автоматически удаляются, как только задачи достигают «выполнено» или «в архиве». Если вы создаёте задачу скриптом с --json (машинный вывод), автоподписка включается — значит, что вызывающие скрипты хотят управлять подписками явно через /kanban notify-subscribe.

Усечение вывода в мессенджерах

Платформы шлюзов имеют практические ограничения по форме окон. Если /kanban list, /kanban show или /kanban Tail выдаёт более ~3800 символов вывода, ответ усекается с нижним колонтитулом … (усечено; викор``hermes kanban...\ в терминале для полного результата)`. CLI-поверхность не имеет таких ограничений.

Автодополнение

В интерактивном интерфейсе CLI вводы /kanban и циклически перезагружает список подкоманд (list, ls, show, create, assign, link, unlink, claim, comment, complete, block, unblock, archive, tail, dispatch, context, init, gc). Остальные глаголы, перечисленные выше в справочнике CLI (watch, stats, runs, log, assignees, heartbeat, notify-subscribe, notify-list, notify-unsubscribe, daemon), а также работают — они просто ещё не в списке подсказок автодополнения.

Шаблоны сотрудничества

Доска этих поддерживает восемь шаблонов без каких-либо новых примитивов:

Шаблон Форма Пример
P1 Разветвление N братьев и сестёр, та же роль "исследовать 5 параллельно"
P2 Конвейер цепочка роли: разведчик → редактор → писатель сборка ежедневного брифинга
P3 Голосование / кворум N братьев и сестёр + 1 агрегатор 3 исследователя → 1 рецензент выбирает
P4 Долгоживущий журнал тот же профиль + общий каталог + cron хранилище Обсидиан
P5 Человек в цикле воркер блокируется → пользователь комментирует → разблокировка неоднозначные решения
P6 @упоминание встроенная маршрутизация из проз @reviewer посмотрел на это
P7 Рабочее пространство с видимой треда /kanban здесь в треде потоковые шлюзы для каждого проекта
P8 Флотская ферма один профиль, N субъектов 50 социальных аккаунтов
P9 Спецификатор триажа грубая идея → triagehermes kanban указать расширение тела → todo "превратить этот однострочник в задачу по спецификации"

Рабочие образцы каждого см. в docs/hermes-kanban-v1-spec.pdf.

Мультиарендаторное использование

Когда один специалист флота обслуживает несколько предприятий, помечайте следующую задачу арендатора:

hermes kanban create "ежемесячный отчёт" \
    --assignee researcher \
    --tenant business-a \
    --workspace dir:~/tenants/business-a/data/

Воркеры получают $HERMES_TENANT и пространственно именуют свои записи в памяти по префиксу. Доска, диспетчер и настройки профилей являются общими; только данные ограничены.

Уведомления шлюза

Когда вы запускаете /kanban create… из шлюза (Telegram, Discord, Slack и т.д.), исходный чат автоматически назначается новой задаче. Фоновый уведомитель шлюза опрашивает task_events несколько секунд и отправляет одно сообщение о каждом терминальном событии («завершено», «блокировано», «gave_up», «crashed», «timed_out») в этом чате. Завершённые задачи также отправляют первую надпись -result воркера, чтобы вы могли видеть результат без необходимости /kanban show.

Вы можете управлять подписками явно из CLI — полезно, когда скрипт / cron хочет уведомить чат, из которого она не была создана:

hermes kanban notify-subscribe t_abcd \
    --platform telegram --chat-id 12345678 --thread-id 7
hermes kanban notify-list
hermes kanban notify-unsubscribe t_abcd \
    --platform telegram --chat-id 12345678 --thread-id 7

Подписка автоматически удаляется, как только задачи достигаются «выполнено» или «в архиве»; очистка не требуется.

Запуски — одна строка на город

Задача — это логическая единица работы; запуск — это одна попытка ее выполнения. Когда диспетчер захватывает готовую задачу, он создает текст в task_runs и указывает tasks.current_run_id на ней. Когда эта попытка завершается — завершена, заблокирована, упала, закончилось время, сбой запуска, отзыв — строка запуска закрывается с «результатом», и указатель задачи очищается. Задача, которая была принята трижды, имеет три строки task_runs.

Две таблицы вместо простого изменения задач: вам нужна полная история изменений для каждого посмертных анализов («Почему ревьюера получила одобрение, третья слила»), и вам нужно чистое место для изучения метаданных каждой попытки — какие файлы изменились, какие тесты запускались, какие выводы отметил ревьюер. Это запуск фактов, а не задача фактов.

Запускаются также показы, где живёт структурированная передача. Когда работник завершит задачу (через kanban_complete(...)), он может передать:

Нижестоящие дочерние задачи читают сводку + метаданные самого последнего завершения запуска для каждого родителя. Повторяющие воркеры читают озвучку своей собственной задачи (результат, сводку, ошибку), чтобы не повторять путь, который уже не удался.

# Что на самом деле делает воркер — вызов инструмента, изнутри цикла агента:
kanban_complete(
    summary="реализовал token bucket, ключи по user_id с запасным IP, все тесты проходят",
    metadata={"changed_files": ["limiter.py", "tests/test_limiter.py"], "tests_run": 14},
    result="ограничитель скорости отправлен",
)

Та же самая передача доступна из CLI, когда вы (человек) должны закрыть задачу, воркер не может — например, задачу, которая была заброшена, или ту, которую вы отметили как выполненную вручную из панели управления:

hermes kanban complete t_abcd \
    --result "ограничитель скорости отправлен" \
    --summary "реализовал token bucket, ключи по user_id с запасным IP, все тесты проходят" \
    --metadata '{"changed_files": ["limiter.py", "tests/test_limiter.py"], "tests_run": 14}'

# Просмотреть историю попыток повторяемой задачи:
hermes kanban runs t_abcd
#   #  OUTCOME       PROFILE           ELAPSED  STARTED
#   1  blocked       worker               12s  2026-04-27 14:02
#        → BLOCKED: нужно решение по ключу rate-limit
#   2  completed     worker                8m   2026-04-27 15:18
#        → реализовал token bucket, ключи по user_id с запасным IP

Запуски отображаются на панели управления (раздел "История запусков" в боковой панели, одна цветная строка на попытку) и в REST API (GET /api/plugins/kanban/tasks/:id возвращает массив runs[]). PATCH /api/plugins/kanban/tasks/:id с {status: "done", summary, metadata} передаёт оба в ядро, поэтому кнопка "отметить как выполненное" на панели управления эквивалентна CLI. Строки task_events содержат run_id, к которому они принадлежат, чтобы UI мог группировать их по попытке, а событие completed встраивает первую строку сводки в свою полезную нагрузку (ограничено 400 символами), чтобы уведомители шлюза могли отображать структурированные передачи без второго SQL-запроса.

Предостережение о массовом закрытии. hermes kanban complete a b c --summary X отклоняется — структурированная передача относится к запуску, поэтому копирование одной и той же сводки для N задач почти всегда неправильно. Массовое закрытие без --summary / --metadata по-прежнему работает для распространённого случая "я закончил кучу административных задач".

Отозванные запуски из-за изменений статуса. Если вы перетаскиваете выполняющуюся задачу из running на панели управления (обратно в ready или сразу в todo) или архивируете задачу, которая всё ещё выполнялась, текущий запуск закрывается с outcome='reclaimed', а не остаётся сиротой. Строка task_runs всегда находится в терминальном состоянии, когда tasks.current_run_id равен NULL, и наоборот — этот инвариант соблюдается в CLI, панели управления, диспетчере и уведомителе.

Синтетические запуски для никогда не захваченных завершений. Завершение или блокировка задачи, которая никогда не была захвачена (например, человек закрывает задачу ready из панели управления со сводкой, или пользователь CLI запускает hermes kanban complete <ready-task> --summary X) иначе потеряло бы передачу. Вместо этого ядро вставляет строку запуска нулевой длительности (started_at == ended_at), несущую сводку / метаданные / причину, чтобы история попыток оставалась полной. run_id события completed / blocked указывает на эту строку.

Обновление боковой панели в реальном времени. Когда поток событий WebSocket панели управления сообщает о новых событиях для задачи, которую пользователь в данный момент просматривает, боковая панель перезагружается (через счётчик событий для каждой задачи, вставленный в список зависимостей useEffect). Закрытие и повторное открытие больше не требуется, чтобы увидеть новую строку запуска или обновлённый результат.

Прямая совместимость

Два nullable столбца в tasks зарезервированы для маршрутизации рабочих процессов v2: workflow_template_id (к какому шаблону принадлежит эта задача) и current_step_key (какой шаг в этом шаблоне активен). Ядро v1 игнорирует их для маршрутизации, но позволяет клиентам их записывать, поэтому релиз v2 может добавить механизм маршрутизации без ещё одной миграции схемы.

Справочник событий

Каждый переход добавляет строку в task_events. Каждая строка несёт опциональный run_id, чтобы UI могли группировать события по попытке. Виды группируются в три кластера для удобства фильтрации (hermes kanban watch --kinds completed,gave_up,timed_out):

Жизненный цикл (что изменилось в задаче как логической единице):

Вид Полезная нагрузка Когда
created {assignee, status, parents, tenant} Задача вставлена. run_id равен NULL.
promoted todo → ready, потому что все родители достигли done. run_id равен NULL.
claimed {lock, expires, run_id} Диспетчер атомарно захватил задачу ready для запуска.
completed {result_len, summary?} Воркер написал --result / --summary, и задача достигла done. summary — это первая строка передачи (ограничение 400 символов); полная версия живёт в строке запуска. Если complete_task вызывается для никогда не захваченной задачи с полями передачи, синтезируется запуск нулевой длительности, чтобы run_id всё ещё указывал на что-то.
blocked {reason} Воркер или человек переключил задачу в blocked. Синтезирует запуск нулевой длительности при вызове для никогда не захваченной задачи с --reason.
unblocked blocked → ready, либо вручную, либо через /unblock. run_id равен NULL.
archived Скрыто из доски по умолчанию. Если задача всё ещё выполнялась, несёт run_id запуска, который был отозван как побочный эффект.

Редактирования (изменения, инициированные человеком, которые не являются переходами):

Вид Полезная нагрузка Когда
assigned {assignee} Назначение изменено (включая снятие назначения).
edited {fields} Заголовок или тело обновлены.
reprioritized {priority} Приоритет изменён.
status {status} Перетаскивание на панели управления записало статус напрямую (например, todo → ready). Несёт run_id запуска, который был отозван при перетаскивании из running; в противном случае run_id равен NULL.

Телеметрия воркера (о процессе выполнения, а не о логической задаче):

Вид Полезная нагрузка Когда
spawned {pid} Диспетчер успешно запустил процесс воркера.
heartbeat {note?} Воркер вызвал hermes kanban heartbeat $TASK для сигнала живости во время длительных операций.
reclaimed {stale_lock} TTL захвата истёк без завершения; задача возвращается в ready.
crashed {pid, claimer} PID воркера больше не жив, но TTL ещё не истёк.
timed_out {pid, elapsed_seconds, limit_seconds, sigkill} Превышено max_runtime_seconds; диспетчер отправил SIGTERM (затем SIGKILL после 5 с льготного периода) и повторно поставил в очередь.
spawn_failed {error, failures} Одна попытка запуска не удалась (отсутствует PATH, рабочее пространство не монтируется, …). Счётчик увеличивается; задача возвращается в ready для повторной попытки.
gave_up {failures, error} Автоматический выключатель сработал после N последовательных spawn_failed. Задача автоматически блокируется с последней ошибкой. N по умолчанию = 5; переопределяется через --failure-limit.

hermes kanban tail <id> показывает их для одной задачи. hermes kanban watch транслирует их по всей доске.

Вне области

Kanban намеренно однопользовательский. ~/.hermes/kanban.db — это локальный SQLite-файл, и диспетчер запускает воркеров на той же машине. Запуск общей доски на двух хостах не поддерживается — нет примитива координации для "воркер X на хосте A, воркер Y на хосте B", и путь обнаружения сбоев предполагает, что PIDs локальны для хоста. Если вам нужно несколько хостов, запустите независимую доску на каждом хосте и используйте delegate_task / очередь сообщений для их соединения.

Спецификация дизайна

Полный дизайн — архитектура, корректность параллелизма, сравнение с другими системами, план реализации, риски, открытые вопросы — находится в docs/hermes-kanban-v1-spec.pdf. Прочитайте его перед тем, как создавать PR, изменяющий поведение.