From cfa45727310fcbefdbfec04d03ed5b7d90bd437e Mon Sep 17 00:00:00 2001 From: vitya Date: Fri, 22 May 2026 18:39:01 +0300 Subject: [PATCH] =?UTF-8?q?tasks:=20round1=20UX=20feedback=20=E2=80=94=206?= =?UTF-8?q?=20dev-tasks=20+=20review=20umbrella=20[board-viewer-ux-round1-?= =?UTF-8?q?review]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User первые впечатления после go-live board.kzntsv.site: - drawer падает TypeError (приватные репо + no browser token; bundle md в build-time — единственно верное решение) - slug не виден на карточке (только в data-attr) - дата без времени, неясный формат - owner-pill дублируется (single-owner whitelist → visual noise) - нет нумерации задач (BV-12 / T-001 shorthand нужен) - done-tail слишком длинный (нужен render-side cutoff/collapse) Все 6 — code-impl в board-viewer (не deploy → не в .admin, per workshop §5). TDD posture везде (project follow tdd-criteria). Drawer bug = critical (clear-impl: bundle md в build-time, root-cause grounded). Show-slug + full-datetime = clear-impl, простой TDD-цикл. Owner-conditional = clear-impl (single vs multi owner branches), 2 fixtures. Task-numbers + done-cutoff = design-first (4 open questions каждый), brainstorm если recommendations не пройдут single-session. + review umbrella 🔵 blocked-by 6 slug'ами (workshop §4 mandatory). Ops-handoff (rebuild image + Portainer pull) — отдельная taska в .admin/[board-viewer-redeploy-ux-round1] (workshop §5). --- .tasks/STATUS.md | 71 +++++++++++++++++++++ .tasks/board-viewer-drawer-bundle-md.md | 43 +++++++++++++ .tasks/board-viewer-ux-done-cutoff.md | 40 ++++++++++++ .tasks/board-viewer-ux-full-datetime.md | 30 +++++++++ .tasks/board-viewer-ux-owner-conditional.md | 29 +++++++++ .tasks/board-viewer-ux-show-slug.md | 25 ++++++++ .tasks/board-viewer-ux-task-numbers.md | 39 +++++++++++ 7 files changed, 277 insertions(+) create mode 100644 .tasks/board-viewer-drawer-bundle-md.md create mode 100644 .tasks/board-viewer-ux-done-cutoff.md create mode 100644 .tasks/board-viewer-ux-full-datetime.md create mode 100644 .tasks/board-viewer-ux-owner-conditional.md create mode 100644 .tasks/board-viewer-ux-show-slug.md create mode 100644 .tasks/board-viewer-ux-task-numbers.md diff --git a/.tasks/STATUS.md b/.tasks/STATUS.md index 5c8cc32..fe7b4b0 100644 --- a/.tasks/STATUS.md +++ b/.tasks/STATUS.md @@ -66,6 +66,77 @@ _Updated: 2026-05-22_ --- +## ⚪ [board-viewer-drawer-bundle-md] — fix `Failed to fetch` в drawer: bundle md-content в build-time + +**Status:** ready (critical bug) +**Where I stopped:** (not started — diagnose grounded: приватные репо + `fetch(rawUrl, {credentials:'omit'})` без auth → Gitea 401/302→login → TypeError. Решение — bundle per-task .md в build-time в JSON/inline script, drawer читает локально.) +**Next action:** см. `board-viewer-drawer-bundle-md.md`. TDD mode. Сначала reader test: `TaskRecord.md_content?: string`. Затем render embeds JSON-bundle. Затем `static/board.js openDrawer` читает local instead of fetch. E2E smoke в browser-driver: 0 запросов на git.kzntsv.site/raw при клике. +**Branch:** master + + +--- + +## ⚪ [board-viewer-ux-show-slug] — показать slug на карточке (сейчас только в data-attr) + +**Status:** ready +**Where I stopped:** (not started) +**Next action:** TDD mode. Failing test в `tests/render.test.ts`: ожидать `...` в output. Impl в `src/render.ts` + CSS в `static/board.css`. Smoke: slug читается на каждой карточке. +**Branch:** master + + +--- + +## ⚪ [board-viewer-ux-full-datetime] — дата + время в явном формате (не только дата) + +**Status:** ready +**Where I stopped:** (not started — 3 design questions: TZ МСК/UTC, format readable/ISO, оставить ли relative «7h». Recommendations внутри `board-viewer-ux-full-datetime.md`.) +**Next action:** TDD mode. Resolve 3 design-вопроса (или принять recommendations: МСК с явным суффиксом, `YYYY-MM-DD HH:MM МСК`, relative сохранить тоненькой строкой). Затем failing test + impl в `src/render.ts`. +**Branch:** master + + +--- + +## ⚪ [board-viewer-ux-owner-conditional] — скрывать owner-pill когда все таски одного owner'а + +**Status:** ready +**Where I stopped:** (not started — текущий VDS whitelist single-owner `OpeItcLoc03/*` → pill дублируется visual noise. Рендерить условно: single-owner → шапка «Owner: X (N repos)», без pill; multi-owner → pill на карточках.) +**Next action:** TDD mode. Два теста (single/multi owner fixtures). Impl в `src/render.ts`. Связанный ops-audit в `.admin/[board-viewer-redeploy-ux-round1]`: verify `auth.toml board_viewer_repos` (по memory `books` = `victor/books`, не `OpeItcLoc03/books`). +**Branch:** master + + +--- + +## ⚪ [board-viewer-ux-task-numbers] — shorthand numbering (BV-12) на карточке + +**Status:** ready (design-first) +**Where I stopped:** (not started — 4 design-вопроса: scope per-repo/global, source-of-truth `` в STATUS.md vs auto-derive, format BV-12 vs T-001, ретроактивно или нет. Recommendations в `board-viewer-ux-task-numbers.md`.) +**Next action:** Resolve 4 design-вопроса (single user-session). Если рекомендации принимаются — TDD impl: parser извлекает `num` из block-comment, render показывает badge. Ретроспективно — отдельный proход «chore: number existing tasks». Если возникает дилемма — `.workshop/.brainstorm/board-viewer-task-numbers.md`. +**Branch:** master + + +--- + +## ⚪ [board-viewer-ux-done-cutoff] — фильтр / cutoff длинного done-tail + +**Status:** ready (design-first) +**Where I stopped:** (not started — 4 design-вопроса: что считать «archive-нужно» (все 🟢 или N дней+), source неизменен (recommend) vs физический archive, default hide vs show-all, тип cutoff (last-N / date / combined). Recommendations в `board-viewer-ux-done-cutoff.md`.) +**Next action:** Resolve design (single user-session или brainstorm). Recommendations: source-неизменен, render-side cutoff = «hide done by default + toggle + last-10 fallback при show». TDD impl: render с N done>cutoff показывает только N + «N more» expander. Если дилемма — `.workshop/.brainstorm/board-viewer-done-cutoff.md`. +**Branch:** master + + +--- + +## 🔵 [board-viewer-ux-round1-review] — review umbrella для 6 UX-fixes round1 + +**Status:** blocked +**Blocker:** board-viewer-drawer-bundle-md, board-viewer-ux-show-slug, board-viewer-ux-full-datetime, board-viewer-ux-owner-conditional, board-viewer-ux-task-numbers, board-viewer-ux-done-cutoff +**Where I stopped:** (not started — открывать когда все 6 импл-таск 🟢) +**Next action:** Independent review subagent'ом (clean context, не имплементер) — TDD-immutability (тесты не переписаны под impl), output-correctness (smoke на live board.kzntsv.site после redeploy), regression check (49 существующих тестов остаются pass). +**Branch:** master + + +--- + diff --git a/.tasks/board-viewer-ux-done-cutoff.md b/.tasks/board-viewer-ux-done-cutoff.md new file mode 100644 index 0000000..f854af7 --- /dev/null +++ b/.tasks/board-viewer-ux-done-cutoff.md @@ -0,0 +1,40 @@ +# board-viewer-ux-done-cutoff + +## Goal + +User: «чаще нужна архивная чистка — очень длинный хвост в done». Колонка 🟢 done растёт без ограничения; visual noise. Нужна фильтрация / cutoff / collapse. + +## Design open questions — РЕШИТЬ ДО ИМПЛА + +1. **Что архивная чистка должна делать на UI-стороне** (источник = STATUS.md остаётся неизменным, чистка — render-time)? + - Hide-by-default + toggle «show done» (текущий `toggleArchived` уже близко к этому, но done ≠ archived) + - Last-N cutoff: показать последние N done (например 10) per column, остальные за «N more…» + - Date-cutoff: показать done за последние 7 / 14 / 30 дней, остальные скрыты + - Combined: hide by default, expander «show older» +2. **Что считается «done для скрытия»?** Все 🟢 или только те у которых close-date старше N дней? +3. **Должен ли source (STATUS.md) фактически archive'ить старые** (физически переносить в отдельный `.tasks/_archive/.md`)? Это уже не UI а layout-вопрос. Recommend: **нет**, source неизменен, всё на UI-стороне — иначе любая повторная сборка ломается при reorganization. +4. **Default:** hide-done by default или show-all? Если hide — user тыкает один раз чтобы увидеть, плюс — чистый default-вид. Recommend hide-by-default + видимый toggle в шапке. + +## Pre-impl + +- Brainstorm перед импл. Если решения 4-х вопросов выше bundle'ятся в один очевидный recommendation — стартовать impl сразу с design-комментарием в decisions log. Если возникает дилемма — `.workshop/.brainstorm/board-viewer-done-cutoff.md`. + +## TDD posture + +**Mode = TDD** (после resolve design). Failing test: render с N done > cutoff показывает только cutoff штук + «N more» link/button. Цикл RED→GREEN. + +## Key files + +- `src/render.ts` (column-rendering — добавить cutoff + expander) +- `static/board.js` (expander click handler) +- `static/board.css` (styling collapsed state) +- `tests/render.test.ts` + +## Acceptance + +- В колонке 🟢 done видны только последние N (число согласовано в design) — остальные скрыты под expander +- Toggle / expander работает (DevTools click test) +- Source STATUS.md не модифицируется (verify через `git status` after smoke) +- Тесты pass + + diff --git a/.tasks/board-viewer-ux-full-datetime.md b/.tasks/board-viewer-ux-full-datetime.md new file mode 100644 index 0000000..acda6f3 --- /dev/null +++ b/.tasks/board-viewer-ux-full-datetime.md @@ -0,0 +1,30 @@ +# board-viewer-ux-full-datetime + +## Goal + +Сейчас карточка показывает `YYYY-MM-DD` + tooltip с full ISO + относительное `7h` (per `board-viewer-card-meta-fix`). User: «хочется видеть дату и время, а не только дату в непонятном форматировании». + +Заменить short ISO на `YYYY-MM-DD HH:MM` (timezone-suffix явный — `МСК` / `UTC`, чтобы не было ambiguity). Relative «7h» оставить (компактный signal recency) или убрать — зависит от ответа user'а в impl-сессии. + +## Design open questions + +- TZ: МСК (UTC+3) или UTC? User в МСК, но board может смотреться из других мест. Recommend МСК с явным суффиксом. +- Format: `2026-05-22 14:35 МСК` или ISO `2026-05-22T14:35+03:00`? Recommend первое — читаемее. +- Relative «7h» — сохранить или убрать? Recommend сохранить как тоненькую вторую строку под датой. + +## TDD posture + +**Mode = TDD**. Failing test для нового format'а в `render.test.ts` (или эквивалент в card-meta-fix tests). Impl в `src/render.ts`. + +## Key files + +- `src/render.ts` (formatLastCommitIso или эквивалент функция) +- `tests/render.test.ts` + +## Acceptance + +- Карточка показывает `2026-05-22 14:35 МСК` (или согласованный format) — не только дату +- Tooltip остаётся (full ISO с секундами для копи-паста) +- Тесты pass с новым форматом + + diff --git a/.tasks/board-viewer-ux-owner-conditional.md b/.tasks/board-viewer-ux-owner-conditional.md new file mode 100644 index 0000000..7b0c128 --- /dev/null +++ b/.tasks/board-viewer-ux-owner-conditional.md @@ -0,0 +1,29 @@ +# board-viewer-ux-owner-conditional + +## Goal + +User: «`OpeItcLoc03` — почему везде один и тот же owner? Зачем он вообще?» Owner-pill добавлен `board-viewer-card-meta-fix` как differentiator для cross-owner whitelist'а, но в текущем VDS-конфиге все 5 репо в одном namespace (`OpeItcLoc03/*`) → pill дублируется на каждой карточке, visual noise. + +Рендерить owner **условно**: если на текущем рендере все видимые карточки имеют один и тот же owner — pill скрыть, owner один раз показать в шапке доски (например «Owner: OpeItcLoc03 (5 repos)»). При ≥2 distinct owners — pill вернуть на карточки. + +## TDD posture + +**Mode = TDD**. Failing test: render с фикстурой single-owner → cards без `.owner-pill`, шапка содержит owner-summary. Render с фикстурой multi-owner → cards содержат `.owner-pill`, шапка без owner-summary (или с list). Затем impl. + +## Key files + +- `src/render.ts` — pre-render scan distinct owners, conditional output +- `static/board.css` — стиль для header owner-summary +- `tests/render.test.ts` — два теста (single-owner / multi-owner fixtures) + +## Acceptance + +- При single-owner whitelist карточки чище (без duplicate pill); owner один раз в шапке +- При multi-owner — pill возвращается, шапка не дублирует +- Тесты pass + +## Notes + +- Связанная ops-проверка (см. `.admin/[board-viewer-redeploy-ux-round1]`): верифицировать что `board_viewer_repos` в `/opt/stacks/board-viewer/auth.toml` корректно — `books` по memory `Gitea owner namespace` должен быть `victor/books`, не `OpeItcLoc03/books`. Если auth.toml корректен и whitelist single-owner — UI conditional работает как задумано. + + diff --git a/.tasks/board-viewer-ux-show-slug.md b/.tasks/board-viewer-ux-show-slug.md new file mode 100644 index 0000000..a6d60ea --- /dev/null +++ b/.tasks/board-viewer-ux-show-slug.md @@ -0,0 +1,25 @@ +# board-viewer-ux-show-slug + +## Goal + +Карточка не показывает slug визуально. Юзер видит только description (первая строка после `## 🟢 [] — `) и не понимает «какая это таска по имени». `data-slug` атрибут есть, но в header карточки не рендерится. + +Добавить slug как видимый sub-heading или badge в верхней части карточки (под/над description-line, в моноширинном шрифте чтобы выделялся). + +## TDD posture + +**Mode = TDD** (project `follow tdd-criteria`). Сначала failing render-test: ожидать что output `renderCard(record)` содержит `board-viewer-pointers` (или эквивалент). Затем impl в `src/render.ts`. + +## Key files + +- `src/render.ts` (рендер карточки — добавить slug-element) +- `static/board.css` (стиль `.card-slug` — monospace, dim color, маленький) +- `tests/render.test.ts` — новый тест + +## Acceptance + +- Slug виден на каждой карточке (любой статус) +- Тест: html-output карточки содержит slug в parseable form (не только в data-атрибуте) +- Smoke: визуально на board.kzntsv.site после redeploy — slug читается, не сливается с description + + diff --git a/.tasks/board-viewer-ux-task-numbers.md b/.tasks/board-viewer-ux-task-numbers.md new file mode 100644 index 0000000..7d59b55 --- /dev/null +++ b/.tasks/board-viewer-ux-task-numbers.md @@ -0,0 +1,39 @@ +# board-viewer-ux-task-numbers + +## Goal + +User: «нам явно не хватает нумерации задач». Сейчас каждая задача — slug (`board-viewer-pointers`). Slug informative, но длинный. Хочется shorthand (`T-001` / `BV-12` / etc.) для разговора, ссылок, memory-references. + +## Design open questions — РЕШИТЬ ДО ИМПЛА + +1. **Scope нумерации:** per-repo (BV-12, BO-3) или global cross-repo (T-78)? Per-repo стабильнее (новый репо не сдвигает существующие numbers). +2. **Источник truth:** хранить number в STATUS.md (комментарий или новый field в block)? Или auto-derive из order/position? + - **Source-of-truth в STATUS.md** — стабильно (number не меняется), но требует ручной maintenance при создании каждой таски. + - **Auto-derive** — нулевая maintenance, но number меняется при reorder/insert. + - Recommend: source-of-truth, с конвенцией «при создании новой таски вписать `` сразу после `## ...` строки». Reader парсит, рендер показывает. +3. **Format:** `BV-12`, `BV12`, `T-001`, `#12`? Recommend `BV-12` — short, читается, не конфликтует с slug. +4. **Старые таски:** нумеровать ретроактивно? Recommend да, один проход — выписать number для каждой существующей таски в каждом репо, commit отдельно «chore: number existing tasks». + +## TDD posture + +**Mode = TDD** (после resolve design-вопросов). Failing test: парсер извлекает `num` из STATUS.md block, render показывает badge с number в карточке. Затем impl. + +## Pre-impl + +- Brainstorm перед коммитом первой строки кода. Дизайн — короткий (4 вопроса выше), может занять одну session-петлю с user. Если будет нужен heavy brainstorm — стартовать `.workshop/.brainstorm/board-viewer-task-numbers.md` через `recommend-don't-menu` мод. + +## Key files + +- `src/parser.ts` (парсинг `` comment) +- `src/render.ts` (badge на карточке) +- STATUS.md всех 5 репо в whitelist (ретроактивная нумерация) +- `tests/parser.test.ts` + `tests/render.test.ts` + +## Acceptance + +- Каждая карточка показывает number-badge (`BV-12`) рядом со slug +- Тесты pass +- Все существующие таски в whitelist-репо имеют `` (или эквивалент) +- Конвенция документирована в `using-tasks` skill (или эквиваленте) — «новые таски имеют number с момента создания» + +