Files
board-viewer/.tasks/board-viewer-drawer-bundle-md.md
vitya cfa4572731 tasks: round1 UX feedback — 6 dev-tasks + review umbrella [board-viewer-ux-round1-review]
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).
2026-05-22 18:39:01 +03:00

44 lines
4.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# board-viewer-drawer-bundle-md
## Goal
Drawer падает с `TypeError: Failed to fetch` при клике на любую карточку. Root-cause: `rawUrl` указывает на `git.kzntsv.site/<owner>/<repo>/raw/branch/<branch>/<path>` — приватные репо требуют auth, в браузере токена нет (он только в build-контейнере для статической генерации, `auth.toml` ro-mounted). Browser fetch без `Authorization` → Gitea отдаёт 401 / 302→login HTML → fetch воспринимает как failure → TypeError.
Решение: **bundle per-task md-content в build-time**. Build-контейнер уже знает где per-task `.md` файлы (он их fetch'ит для парсинга), у него есть Gitea token. Расширить read-фазу: вместе с STATUS.md тянуть и per-task .md (если существует), складывать в `dist/tasks-md.json` или встраивать в `<script type="application/json" id="tasks-md">…</script>` в `index.html`. Drawer читает из этого локального data вместо fetch.
## TDD posture
**Mode = TDD** (project CLAUDE.md имеет `follow tdd-criteria`). Failing test первым:
- Unit: reader получает per-task md content параллельно с STATUS.md, кладёт в `TaskRecord.md_content?: string`
- Render: каждая карточка имеет `data-md-encoded` или используется shared JSON-bundle с `data-md-key={slug}`
- Drawer test (board.js): открывает draweр по data-key, читает из bundled JSON, рендерит через `marked.parse` — без fetch
- E2E smoke: открыть локально dist/index.html в browser-driver (или mocked DOM), кликнуть карту → drawer показывает md content, не «Failed to load»
## Key files
- `src/gitea.ts` — добавить метод `getRawContent(owner, repo, path)` через API (`/api/v1/repos/.../contents/`+base64-decode или `/api/v1/repos/.../raw/...` с токеном)
- `src/reader.ts` — расширить чтобы для каждого `TaskRecord` пулить per-task `.md` (если file exists)
- `src/render.ts:136` — добавить data-md-key вместо data-raw-url, либо встроить JSON-bundle в html
- `static/board.js:200-215``openDrawer` читает из localStorage / global var вместо fetch
- `tests/` — fixture для per-task md, новые тесты
## Acceptance criteria
- Все 49 текущих тестов всё ещё pass + новые тесты для md-bundle pipeline
- E2E smoke на real board.kzntsv.site (live): клик на любую карту → drawer заполняется per-task content без network-запросов на git.kzntsv.site
- DevTools Network: открыть карту → 0 запросов исходящих к git.kzntsv.site/raw
- Размер `index.html` или `tasks-md.json` reasonable (предположительно <500 KB на 80 records — markdown текстовый, gzip сильно сожмёт)
- Карты без per-task `.md` файла (status=ready без deep-context) — drawer показывает только title + status block, без «Failed to load»
## Decisions log
- 2026-05-22: создана из user UX-feedback round1 — drawer ломается с TypeError. Root-cause grounded: приватные репо + no browser token. Импл-направление = bundle, не proxy (proxy потребовал бы nginx с auth_request к board-viewer-build или Gitea token в nginx — переусложнение). Bundle deterministic + no runtime network.
## Notes
- Bundle approach впишется в существующий cron-loop pattern (build every 300s регенирует index.html + tasks-md). Никаких runtime-зависимостей от Gitea API.
- Файлы могут быть rotated/архивированы (см. сестринскую таску `board-viewer-ux-done-cutoff`).
<!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: .workshop / 2026-05-22 / trigger: user-ux-feedback-round1 -->