promote: workshop/board-viewer brainstorm → concepts + 5 tasks

- concepts/board-viewer.md (design, promoted from .workshop)
- .tasks/STATUS.md + 5 per-task files:
  - board-viewer-pointers (pre-impl, status=ready)
  - board-viewer-gitea-reader (impl, TDD, status=ready)
  - board-viewer-html-render (impl, TDD, blocker=gitea-reader)
  - board-viewer-cron-deploy (impl, infra carve-out, blocker=html-render)
  - board-viewer-review (umbrella, status=blocked)

TDD-mode embedded in impl-tasks per follow tdd-criteria trigger in CLAUDE.md.
MCP write-side workaround per memory reference_projects_meta_resolveTarget_bug.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
vitya
2026-05-22 08:21:59 +03:00
parent d0dc686a65
commit 27465089b5
9 changed files with 414 additions and 15 deletions

View File

@@ -0,0 +1,105 @@
---
title: Board viewer — design
type: concept
date: 2026-05-22
status: promoted
source: .workshop/.archive/2026-05-22-board-viewer.md
sources:
- https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban
- https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban-tutorial
- .tasks/STATUS.md per-project emoji-словарь (⚪🟡🟣🔴🟢)
- mcp__projects-meta__tasks_aggregate (текстовый кросс-проектный вид)
---
# Board viewer — визуал прогресса по таскам
## Контекст
Сейчас визуала прогресса по таскам нет — есть только текстовые формы: `.tasks/STATUS.md` per-project с emoji-легендой (⚪ open / 🟡 in-progress / 🟣 paused / 🔴 blocked / 🟢 done) и `mcp__projects-meta__tasks_aggregate` поверх Gitea-репо `OpeItcLoc03/agenda`. Цель — визуальная kanban-доска для глаз.
## Что увидено у hermes-agent
Их kanban — не «доска», а **execution engine**:
- SQLite-DB `~/.hermes/kanban.db` как SoT.
- 6 колонок: `triage / todo / ready / running / blocked / done` (+ `archived`).
- Dispatcher каждые 60s спавнит workers, workers общаются с доской через тулсы (`kanban_show`, `kanban_heartbeat`, `kanban_complete`, `kanban_block`).
- Decomposer auto-fans `triage``todo` через специальный профиль.
- Circuit-breaker: 2 фейла подряд → auto-block.
- Web-dashboard с drag-drop, multi-select, run-history per task.
- CLI: `hermes kanban create/show/runs/decompose/watch/notify-subscribe`.
- REST API `/api/plugins/kanban/`.
- Single-host by design (cite: «~/.hermes/kanban.db is a local SQLite file ... Running a shared board across two hosts is not supported»).
Это **мультиагентский оркестратор**, где kanban — UI-слой. **Это другой кейс**, чем наш — выделили в отдельный буфер `agent-orchestration-without-user.md` (там идёт самостоятельное обсуждение).
## Решение: read-only HTML kanban-viewer над Gitea API, хостинг на VDS
**Что:** маленький HTTP-сервис на VDS (рядом с Gitea, traefik уже там), который читает Gitea API напрямую (`OpeItcLoc03/agenda` + per-project репо) и рендерит 5-колоночную доску по emoji-словарю: ⚪ open / 🟡 in-progress / 🟣 paused / 🔴 blocked / 🟢 done.
**Где:** домен `board.kzntsv.site` за traefik, рядом с `git.kzntsv.site`.
**Как обновляется:** cron-тик каждые ~5 мин, перегенерация статической HTML. Realtime не нужен — таски меняются раз в сессию.
**SoT не меняется:** `.tasks/<slug>.md` + `STATUS.md` в каждом проекте, Gitea `agenda` репо как backend. Markdown остаётся grep-able, git-blameable, скилы `using-tasks`/`setup-tasks` не ломаются.
**Размер:** ~200-300 LOC сервис + traefik label + cron-таймер.
## Implementation note — почему Gitea API, а не MCP
В исходном брейнсторме предполагалось «дергает `mcp__projects-meta__tasks_aggregate` или читает Gitea API напрямую». **Это ложная развилка:** `mcp__projects-meta__*` доступен только внутри Claude Code-контекста, у HTTP-сервиса этой шины нет. Реальный единственный путь — **прямой Gitea API** (`GET /api/v1/repos/OpeItcLoc03/agenda/contents/...`) с тем же admin-токеном из `~/.config/projects-mcp/auth.toml`. По сути — переписываем кусок логики `tasks_aggregate` поверх HTTP, не «дёргаем готовое».
## Почему не hermes-стиль
Hermes kanban — это execution engine. Dispatcher спавнит workers, агенты heartbeat'ят, circuit-breaker блокирует таску после 2 фейлов, decomposer фанаут'ит triage→todo автоматически. Это нужно когда у тебя автономный fleet агентов работает без человека. У нас другой паттерн: **визуальный прогресс** ≠ оркестрация. Импортировать их dispatcher/worker модель ради UI-слоя — купить большой движок ради картинки.
Тема «автономные cross-project агенты» обсуждается отдельно в `agent-orchestration-without-user.md`. Если она дойдёт до промоушена — там может появиться execution engine, и viewer станет естественной мордой к нему. **Viewer от него не зависит**: над `.tasks/*.md` он работает уже сейчас.
## Почему не Gitea Projects
Gitea Projects работает поверх **issues** одного репо. Чтобы он стал нашей доской — надо мигрировать `.tasks/<slug>.md` → Gitea issues как первичный носитель. Цена:
- ❌ убивается markdown grep по проекту,
- ❌ ломаются скилы `using-tasks`/`setup-tasks`, которые ждут per-task `.md` файлы,
- ❌ git-история per-task переезжает в БД Gitea, не в `git log`.
Слишком высокая цена ради drag-drop.
## Trade-offs честно
| Минус | Что значит |
|---|---|
| read-only | drag-drop статуса нет; меняем через редактирование `.md` (как сейчас) |
| 5-мин лаг | не realtime; ок для таск-доски, не ок для лога инцидентов |
| зависит от Gitea API | если Gitea упадёт — доска показывает stale (но это уже catastrophic incident) |
Drag-drop **разблокируется автоматически** когда починим `projects-meta` write-side bug cluster — см. memory `reference_projects_meta_resolveTarget_bug.md`. Это уже в плане работ по `projects-meta`, не блокер этого проекта.
## Что внутри viewer'а — MVP
- **5-колоночный board** по статусам (без `triage`/`ready` — наш словарь иной).
- **Карточка таски:** title, проект, owner (если есть), age (since open), последний коммит-маркер.
- **Группировка по проекту** опционально (toggle «по статусам vs по проектам»).
- **Поиск/фильтр** по проекту, тегам, owner'у — клиент-сайд JS (нет API за пределами initial-load).
- **Per-card drawer** показывает full markdown из `<slug>.md` (lazy-fetch из Gitea raw).
- **Refresh-таймер** видно на странице.
Чего точно нет в MVP:
- write-side ничего (drag-drop, edit, create);
- realtime обновления (WS, SSE);
- multi-tenant (пока один юзер);
- auth (это traefik basic-auth, не in-app);
- run history (это уровень оркестратора, не viewer'а).
## Зависимости
- Прямой read Gitea API к `OpeItcLoc03/agenda` + per-project репо — **уже работает**.
- traefik route + DNS на `board.kzntsv.site` — стандартная инфра VDS.
- cron tick — systemd timer или `vds-job-scheduler` (если поднимем) — на выбор при имплементации.
Ничего блокирующего.
## Связь с `agent-orchestration-without-user.md`
Viewer — независимый артефакт. Он читает текущий `.tasks/*.md` SoT, и продолжит работать как-есть после промоушена оркестратора (тот добавляет поля типа `owner`, `claim_token` — viewer просто отрендерит их в карточке). **Не блокируется ничем из orchestration-брейнсторма**, не блокирует его.