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:
@@ -1,21 +1,51 @@
|
||||
# Task Board
|
||||
_Updated: 2026-05-22_
|
||||
|
||||
## ⚪ [board-viewer-pointers] — pre-impl: fill Domain conventions with design-context pointers
|
||||
**Status:** ready
|
||||
**Where I stopped:** только что промочен дизайн из `.workshop/.brainstorm/board-viewer.md` в `concepts/board-viewer.md`; `.wiki/CLAUDE.md` ещё содержит дефолтный setup-wiki stub в Domain conventions, без ссылок на дизайн.
|
||||
**Next action:** вставить блок «Mandatory: read design context before implementation» в `.wiki/CLAUDE.md` Domain conventions (готовый текст в `board-viewer-pointers.md`), коммит `wiki(claude): add design-context pointers for board-viewer`, push.
|
||||
**Branch:** master
|
||||
|
||||
---
|
||||
|
||||
## ⚪ [board-viewer-gitea-reader] — Gitea API reader → normalized task structure
|
||||
**Status:** ready
|
||||
**Where I stopped:** дизайн зафиксирован, реализация не начата. Это первая импл-таска, остальные impl-таски зависят от её типов.
|
||||
**Next action:** прочитать `board-viewer-pointers.md` next-action блок → выполнить `board-viewer-pointers` сначала; затем стартовать с TDD по контракту в `board-viewer-gitea-reader.md`.
|
||||
**Blocker:** board-viewer-pointers (нет Domain conventions с указанием на спецификацию)
|
||||
**Branch:** master
|
||||
|
||||
---
|
||||
|
||||
## ⚪ [board-viewer-html-render] — render 5-col kanban from normalized structure
|
||||
**Status:** ready
|
||||
**Where I stopped:** ждёт `board-viewer-gitea-reader` (использует его типы).
|
||||
**Next action:** после ready-стейта reader'а — TDD по контракту в `board-viewer-html-render.md`.
|
||||
**Blocker:** board-viewer-gitea-reader
|
||||
**Branch:** master
|
||||
|
||||
---
|
||||
|
||||
## ⚪ [board-viewer-cron-deploy] — systemd timer + traefik + DNS on VDS
|
||||
**Status:** ready
|
||||
**Where I stopped:** ждёт `board-viewer-html-render` (нужен артефакт для деплоя).
|
||||
**Next action:** после готового HTML-рендера — добавить traefik label, DNS A-запись `board.kzntsv.site`, systemd timer на ~5 мин, basic-auth через traefik. См. `board-viewer-cron-deploy.md`.
|
||||
**Blocker:** board-viewer-html-render
|
||||
**Branch:** master
|
||||
|
||||
---
|
||||
|
||||
## 🔵 [board-viewer-review] — review checkpoint (umbrella)
|
||||
**Status:** blocked
|
||||
**Where I stopped:** дизайн зафиксирован, импл ещё не начата.
|
||||
**Next action:** дождаться 🟢 у всех blocker-тасок (включая `board-viewer-pointers`). Прочитать спецификацию `.wiki/concepts/board-viewer.md`. Для каждой импл-таски: `git log --oneline`, прогнать тесты, сверить с acceptance criteria. Findings → follow-up tasks через `mcp__projects-meta__tasks_create`.
|
||||
**Blocker:** board-viewer-pointers; board-viewer-gitea-reader; board-viewer-html-render; board-viewer-cron-deploy
|
||||
**Branch:** master
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
Add one block per task, sorted by priority. Use the emoji status legend below.
|
||||
Per-task deep context lives in .tasks/<task-slug>.md (created on demand by using-tasks).
|
||||
|
||||
Block format:
|
||||
|
||||
## 🔴 [task-slug] — short description
|
||||
**Status:** active
|
||||
**Where I stopped:** one sentence — the exact thought or action interrupted
|
||||
**Next action:** one concrete step to resume immediately
|
||||
**Blocker:** (only if blocked) what is preventing progress
|
||||
**Branch:** git branch name
|
||||
|
||||
---
|
||||
|
||||
Status legend:
|
||||
🔴 Active — only one at a time
|
||||
🟡 Paused — in progress, resumable
|
||||
|
||||
44
.tasks/board-viewer-cron-deploy.md
Normal file
44
.tasks/board-viewer-cron-deploy.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# board-viewer-cron-deploy
|
||||
|
||||
## Goal
|
||||
|
||||
Деплой статической HTML-доски на VDS под доменом `board.kzntsv.site`. Periodic regen через systemd timer ~5 мин. Traefik label для роутинга. DNS A-запись. Basic-auth через traefik (не in-app).
|
||||
|
||||
**TDD posture:** под carve-out «infrastructure / declarative» из `tdd-criteria`. Acceptance проверяется по факту deploy + curl, не unit-тестами. systemd unit-файлы и traefik labels — декларативные конфиги, не код.
|
||||
|
||||
## Key files
|
||||
|
||||
- (TBD) `deploy/board-viewer.service` — systemd one-shot unit (runs reader + render → writes to `/var/www/board-viewer/`)
|
||||
- (TBD) `deploy/board-viewer.timer` — systemd timer (OnUnitActiveSec=5min)
|
||||
- (TBD) `deploy/docker-compose.yml` фрагмент или `deploy/traefik-labels.yaml` — traefik label для статики
|
||||
- (TBD) `deploy/README.md` — install steps + DNS record requirements
|
||||
- (TBD) `deploy/auth/htpasswd` — basic-auth credentials (gitignored, with `.htpasswd.example`)
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- DNS `board.kzntsv.site` → VDS IP (Cloudflare / namecheap / wherever DNS живёт).
|
||||
- Traefik route: `board.kzntsv.site` → static file serving из `/var/www/board-viewer/`.
|
||||
- Basic-auth на traefik (middleware), креды из `.htpasswd`.
|
||||
- systemd timer крутится каждые 5 мин, успешно дёргает reader + render, пишет в `/var/www/board-viewer/index.html`.
|
||||
- Логи systemd видны через `journalctl -u board-viewer.service`.
|
||||
- Health check: `curl -u user:pass https://board.kzntsv.site/` → HTML с актуальной доской.
|
||||
- README.md описывает install steps (для disaster-recovery: «как поднять с нуля на новой машине»).
|
||||
|
||||
## Decisions log
|
||||
|
||||
- 2026-05-22: task создан промоушеном; carve-out из TDD под инфра (declarative configs).
|
||||
- 2026-05-22: auth = traefik basic-auth, не in-app (фиксировано в дизайне).
|
||||
|
||||
## Open questions
|
||||
|
||||
- [ ] Хост: VDS Rusonyx (тот, где уже Gitea + traefik) или отдельная машина? — VDS, рядом с git.kzntsv.site (см. дизайн).
|
||||
- [ ] Multi-user basic-auth или single creds? — пока single, поскольку single-user проект.
|
||||
- [ ] Rate-limit на Gitea API: 5-мин тик * N репо * M файлов — оценить, не упрётся ли. Gitea дефолт ~60 req/min anon, токенизированный сильно выше — должно хватить с запасом.
|
||||
|
||||
## Completed steps
|
||||
|
||||
- [ ] (фиксируется при выполнении)
|
||||
|
||||
## Notes
|
||||
|
||||
Зависит от `board-viewer-html-render` — нужен артефакт для деплоя (хотя бы placeholder). Можно стартовать параллельно с DNS-записью (она прогревается).
|
||||
59
.tasks/board-viewer-gitea-reader.md
Normal file
59
.tasks/board-viewer-gitea-reader.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# board-viewer-gitea-reader
|
||||
|
||||
## Goal
|
||||
|
||||
Модуль, который через Gitea API читает `.tasks/STATUS.md` + per-task `<slug>.md` файлы из всех релевантных репо (`OpeItcLoc03/agenda` + per-project репо из `~/.config/projects-mcp/auth.toml::gitea_owners`) и нормализует в типизированную структуру для рендера.
|
||||
|
||||
Это первая импл-таска. Остальные импл-таски (`board-viewer-html-render`, `board-viewer-cron-deploy`) зависят от типов, которые этот модуль публикует.
|
||||
|
||||
**TDD-mode:** обязательно по `follow tdd-criteria` триггеру в `.wiki/CLAUDE.md`. Сначала тесты на нормализацию пар фикстур (STATUS.md + per-task.md) → потом реализация. Не модифицировать assert'ы во время реализации без `[test-modify: ...]` маркера в commit subject.
|
||||
|
||||
## Key files
|
||||
|
||||
- (TBD) `src/gitea-reader.{ts,py}` — main reader module
|
||||
- (TBD) `src/types.{ts,py}` — exported task structure
|
||||
- (TBD) `tests/fixtures/` — sample STATUS.md + per-task.md pairs from real repos
|
||||
- (TBD) `tests/gitea-reader.test.{ts,py}` — TDD assertions
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- **Output contract:** массив объектов с полями:
|
||||
```
|
||||
{
|
||||
slug: string,
|
||||
project: string, // repo name (e.g. "board-viewer", "books")
|
||||
project_owner: string, // gitea owner (e.g. "OpeItcLoc03")
|
||||
status: "open" | "in_progress" | "paused" | "blocked" | "done",
|
||||
status_emoji: "⚪" | "🟡" | "🟣" | "🔴" | "🟢",
|
||||
title: string, // from STATUS.md block H2 after slug
|
||||
where_stopped: string | null,
|
||||
next_action: string | null,
|
||||
blocker: string | null,
|
||||
branch: string | null,
|
||||
last_commit_iso: string | null, // from Gitea API, latest commit touching the task file
|
||||
raw_url: string, // Gitea raw URL to per-task <slug>.md for drawer lazy-fetch
|
||||
}
|
||||
```
|
||||
- **Inputs:** список репо из конфига (env var или TOML).
|
||||
- **Auth:** Gitea token из `~/.config/projects-mcp/auth.toml::gitea_token` (admin scope, читает любой репо).
|
||||
- **Robustness:** репо без `.tasks/` → пропустить молча (не ошибка). `.tasks/STATUS.md` без emoji-блоков → пустой массив для этого проекта.
|
||||
- **Tests:** фикстуры из ≥3 реальных репо (board-viewer, books, .workshop), assertions покрывают: нормальный case, status без per-task.md (только STATUS.md block), per-task без записи в STATUS.md (legacy), blocked-таски с `Blocker:` строкой.
|
||||
- **Single language:** один из TS / Python. Выбор — за имплементером (TS легче переиспользует с HTML-рендером в одном процессе; Python проще читать конфиг).
|
||||
|
||||
## Decisions log
|
||||
|
||||
- 2026-05-22: task создан промоушеном; контракт фиксирован — это публичный API для html-render.
|
||||
|
||||
## Open questions
|
||||
|
||||
- [ ] TS or Python? (повлияет на структуру cron-deploy).
|
||||
- [ ] Owner-фильтр: брать репо из `gitea_owners` целиком или whitelist? Возможно нужен `board_viewer_repos` отдельным полем в auth.toml.
|
||||
- [ ] Кэшировать ответы Gitea API локально между cron-тиками? (опт.: rate-limit, hot-reload).
|
||||
|
||||
## Completed steps
|
||||
|
||||
- [ ] (фиксируется при выполнении)
|
||||
|
||||
## Notes
|
||||
|
||||
NB: исходный буфер упоминал `mcp__projects-meta__tasks_aggregate` как возможный источник — **это ложная развилка**, MCP недоступен HTTP-сервису. Только прямой Gitea API. См. `.wiki/concepts/board-viewer.md` секцию «Implementation note».
|
||||
48
.tasks/board-viewer-html-render.md
Normal file
48
.tasks/board-viewer-html-render.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# board-viewer-html-render
|
||||
|
||||
## Goal
|
||||
|
||||
Рендер 5-колоночного kanban-board из нормализованной структуры (продукт `board-viewer-gitea-reader`). Статический HTML + минимальный клиент-сайд JS для фильтра / drawer / refresh-таймера. Без write-side, без realtime.
|
||||
|
||||
**TDD-mode:** обязательно по `follow tdd-criteria`. Снапшот-тесты на HTML-output из фиксированных reader-фикстур. Не модифицировать assert'ы без `[test-modify: ...]` маркера. Визуальная отделка (CSS) — под carve-out «visual CSS», но логика рендера (распределение по колонкам, age-расчёт, drawer-привязка) — TDD.
|
||||
|
||||
## Key files
|
||||
|
||||
- (TBD) `src/render.{ts,py}` — main renderer
|
||||
- (TBD) `templates/board.html` — template (Mustache / Jinja / template literals — выбор имплементера)
|
||||
- (TBD) `static/board.css`, `static/board.js` — styling + filter/drawer client-side
|
||||
- (TBD) `tests/render.test.{ts,py}` — snapshot tests
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- **5 колонок** по статусам: ⚪ open / 🟡 in-progress / 🟣 paused / 🔴 blocked / 🟢 done. Названия колонок — emoji + слово.
|
||||
- **Карточка:**
|
||||
- title (truncate на 80 chars в default-view),
|
||||
- project badge (e.g. `books`, `board-viewer`),
|
||||
- owner (если есть) — pill,
|
||||
- age — относительное (`3d`, `2w`, `5mo`) от `last_commit_iso`,
|
||||
- last-commit-marker — короткий hash или дата.
|
||||
- **Группировка по проекту** — toggle вверху: «по статусам» (5 колонок × проекты внутри) vs «по проектам» (per-project колонки × статусы внутри).
|
||||
- **Поиск/фильтр** — клиент-сайд input: substring по `slug`, `title`, `project`; multi-select по статусам.
|
||||
- **Per-card drawer** — клик по карточке → side panel с full markdown из per-task `<slug>.md` (lazy-fetch из `raw_url`). Markdown рендерится клиент-сайд (e.g. `marked` для TS, `markdown-it` для Py-side-rendered).
|
||||
- **Refresh-таймер** видно в header: «refreshed Xm ago, next in Ym» (data attribute из generation timestamp).
|
||||
- **Output:** один `index.html` файл + sidecar `static/`. Открывается локально без сервера для smoke-test.
|
||||
- **Tests:** snapshot-тесты на 3 reader-фикстуры (пустая доска / 1-2 таски / N≥10 тасок). Snapshots checked-in.
|
||||
|
||||
## Decisions log
|
||||
|
||||
- 2026-05-22: task создан промоушеном; зависит от `board-viewer-gitea-reader` контракта.
|
||||
|
||||
## Open questions
|
||||
|
||||
- [ ] Markdown-renderer: client-side (`marked`) или server-side (Jinja с pre-rendered HTML вшито в data-attr)? Client-side проще — но добавляет ~50KB JS.
|
||||
- [ ] CSS framework: ничего (raw CSS) / Pico / Tailwind via CDN? Минимализм — за raw. Раздёргать через первый прототип.
|
||||
- [ ] Архивные таски (🟢 done старше N дней) скрывать по умолчанию? Toggle?
|
||||
|
||||
## Completed steps
|
||||
|
||||
- [ ] (фиксируется при выполнении)
|
||||
|
||||
## Notes
|
||||
|
||||
Стиль: минимализм без аватарок/гифок/анимаций. Это инструмент глядеть на доску, не дашборд для презентации. Whitespace + типографика.
|
||||
57
.tasks/board-viewer-pointers.md
Normal file
57
.tasks/board-viewer-pointers.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# board-viewer-pointers
|
||||
|
||||
## Goal
|
||||
|
||||
Pre-impl bootstrap: заполнить `.wiki/CLAUDE.md` секцию «Domain conventions» pointer-блоком на спецификацию. Дизайн не лежит в этом репо целиком — только pointer-stub. Без этой таски следующий агент попадёт в дыру: dense `where_stopped` one-liner + пустой Domain conventions stub = угадывание архитектуры вместо чтения готовых решений.
|
||||
|
||||
**Кто делает:** любой следующий агент в этом проекте. Это **первая** по приоритету таска промоушена — все импл-таски ссылаются на pointers через `.wiki/CLAUDE.md`.
|
||||
|
||||
## Key files
|
||||
|
||||
- `.wiki/CLAUDE.md` — Domain conventions section
|
||||
- `.wiki/concepts/board-viewer.md` — canonical design (target of pointer)
|
||||
- `~/projects/.workshop/.archive/2026-05-22-board-viewer.md` — brainstorm rationale (target of pointer)
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- `.wiki/CLAUDE.md` содержит блок «Mandatory: read design context before implementation» в Domain conventions (см. Next action ниже — дословный текст).
|
||||
- Коммит с message `wiki(claude): add design-context pointers for board-viewer`.
|
||||
- Push в `origin/master`.
|
||||
|
||||
## Next action (готовый блок для копирования в `.wiki/CLAUDE.md` Domain conventions)
|
||||
|
||||
Заменить существующий комментарий-stub в секции `## Domain conventions` на следующий блок:
|
||||
|
||||
```markdown
|
||||
### Mandatory: read design context before implementation
|
||||
|
||||
Before picking up any task in `.tasks/`, load the full design context. It does **not** live in this repo fully — only pointers do. Sources, in order:
|
||||
|
||||
1. **Canonical design:** `.wiki/concepts/board-viewer.md`. Architecture decisions, scope, MVP feature list, anti-patterns (hermes-style, Gitea Projects), trade-offs.
|
||||
2. **Brainstorm process trace (rationale):** `~/projects/.workshop/.archive/2026-05-22-board-viewer.md`. Why each decision was made, what was rejected and why, clarifying note that `mcp__projects-meta__*` is not callable from HTTP service.
|
||||
3. **Local `overview.md`** — quick orientation summary; never source of truth.
|
||||
|
||||
Do **not** invent thresholds, taxonomies, container topology, or pipeline stages from task `where_stopped` lines alone — those are pointers, not specifications.
|
||||
|
||||
### TDD posture
|
||||
|
||||
Per `follow tdd-criteria` trigger in this CLAUDE.md: impl-tasks `board-viewer-gitea-reader` and `board-viewer-html-render` are TDD. `board-viewer-cron-deploy` falls under the infrastructure carve-out (declarative systemd / traefik / DNS — verify by deploy + curl, not unit tests). Mark each impl commit accordingly.
|
||||
```
|
||||
|
||||
После вставки: коммит, push.
|
||||
|
||||
## Decisions log
|
||||
|
||||
- 2026-05-22: pointers task создан промоушеном из `.workshop/.brainstorm/board-viewer.md` (workshop-promote-brainstorm).
|
||||
|
||||
## Open questions
|
||||
|
||||
- [ ] (нет — pointer-блок самодостаточен)
|
||||
|
||||
## Completed steps
|
||||
|
||||
- [ ] (фиксируется при выполнении)
|
||||
|
||||
## Notes
|
||||
|
||||
Pointer-таска намеренно тривиальная — её существование защищает следующего агента от чтения stub'а вместо спецификации. Не объединять с импл-тасками.
|
||||
54
.tasks/board-viewer-review.md
Normal file
54
.tasks/board-viewer-review.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# board-viewer-review
|
||||
|
||||
## Goal
|
||||
|
||||
Code-review checkpoint для брейнсторма `board-viewer` (промоушен 2026-05-22).
|
||||
|
||||
**Спецификация:** `.wiki/concepts/board-viewer.md`.
|
||||
**Pre-impl bootstrap:** `board-viewer-pointers` (заполнил `.wiki/CLAUDE.md` Domain conventions — без него review бы читал stub).
|
||||
**Импл-таски (review против их acceptance criteria):** `board-viewer-gitea-reader`, `board-viewer-html-render`, `board-viewer-cron-deploy`.
|
||||
|
||||
**Кто делает:** **не имплементер.** Следующая сессия в этом проекте (другая модель / другой день / другой агент) поднимает таску с чистым контекстом. «Я только что это написал» bias = главный риск.
|
||||
|
||||
## Key files
|
||||
|
||||
- `.wiki/concepts/board-viewer.md` — canonical design
|
||||
- `.tasks/board-viewer-*.md` — acceptance criteria per impl-task
|
||||
- `~/projects/.workshop/.archive/2026-05-22-board-viewer.md` — brainstorm rationale
|
||||
|
||||
## Acceptance criteria (для самого ревью)
|
||||
|
||||
- Прочитана спецификация целиком.
|
||||
- `git log --oneline` shipped-коммитов (по slug или scope в commit-message) сверен с acceptance criteria каждой импл-таски.
|
||||
- Для каждой импл-таски: прогнан соответствующий тест-suite, проверено что тесты реально доходят до своих веток (не coverage-illusion).
|
||||
- Сверены дизайн-decisions со shipped-кодом: контракт reader → render, статика + cron на VDS, отсутствие write-side.
|
||||
- Findings зафайлены как follow-up tasks (`board-viewer-<gap>-fix` или подобное) через `mcp__projects-meta__tasks_create`, либо ревьюер подтвердил «нет findings» в close-note.
|
||||
|
||||
## Чек-лист ревью (poll-выполнения)
|
||||
|
||||
- [ ] reader: контракт публичных полей сохранён (не сужен, не расширен молча)
|
||||
- [ ] reader: фикстуры покрывают edge cases (legacy без per-task.md, blocked с blocker-строкой)
|
||||
- [ ] render: snapshot-тесты обновлены вместе с изменениями (не закоммичен код без апдейта snapshot)
|
||||
- [ ] render: визуально не AI-generic, минимализм соблюдён
|
||||
- [ ] cron-deploy: systemd unit + timer проверены `systemctl status`, не только запущены
|
||||
- [ ] cron-deploy: basic-auth проверена `curl` с верными / неверными кредами
|
||||
- [ ] auth scope: пушится ли токен в публичный репо случайно? (`grep -r "02a14e" deploy/` должен быть пуст)
|
||||
- [ ] disaster recovery: README.md в deploy/ достаточен чтобы поднять с нуля?
|
||||
|
||||
## Decisions log
|
||||
|
||||
- 2026-05-22: review-task создан промоушеном; status=blocked, blocker = все 4 импл-таски.
|
||||
|
||||
## Open questions
|
||||
|
||||
- [ ] (заполняется ревьюером по ходу)
|
||||
|
||||
## Completed steps
|
||||
|
||||
- [ ] (фиксируется при выполнении)
|
||||
|
||||
## Notes
|
||||
|
||||
**Закрытие:** только когда все findings зафайлены ИЛИ ревьюер подтвердил «нет findings» в close-note.
|
||||
|
||||
**TDD-immutability:** если ревью обнаружит модифицированные assert'ы без `[test-modify: ...]` маркера в commit subject — это нарушение `follow tdd-criteria`, finding обязателен.
|
||||
Reference in New Issue
Block a user