task(review): independent review done, findings filed
closes board-viewer-review Subagent code-review against design spec + acceptance criteria found: - 2 Major: README emoji legend stale (board-viewer-readme-emoji-fix), card meta missing owner pill + last-commit-marker (board-viewer-card-meta-fix) - 6 minor/nitpick bundled as board-viewer-polish All shipped code: 43/43 tests pass, TDD-immutability clean, secret hygiene OK. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -33,11 +33,34 @@ _Updated: 2026-05-22_
|
||||
|
||||
---
|
||||
|
||||
## 🔵 [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
|
||||
## 🟢 [board-viewer-review] — review checkpoint (umbrella)
|
||||
**Status:** done
|
||||
**Where I stopped:** independent review выполнен subagent'ом (clean context, не имплементер). 43/43 тестов pass, secret hygiene clean, TDD-immutability чисто. 2 Major + 6 minor/nitpick findings зафайлены как follow-up таски ниже.
|
||||
**Next action:** взять одну из ⚪ fix-тасок (readme-emoji или card-meta).
|
||||
**Branch:** master
|
||||
|
||||
---
|
||||
|
||||
## ⚪ [board-viewer-readme-emoji-fix] — fix stale emoji legend in README.md
|
||||
**Status:** ready
|
||||
**Where I stopped:** review нашёл; trivial 1-line fix.
|
||||
**Next action:** обновить `README.md:5` на `⚪ open / 🔴 in-progress / 🟡 paused / 🔵 blocked / 🟢 done` + заполнить TBD "Quick start" блок.
|
||||
**Branch:** master
|
||||
|
||||
---
|
||||
|
||||
## ⚪ [board-viewer-card-meta-fix] — add owner pill + last-commit-marker to cards
|
||||
**Status:** ready
|
||||
**Where I stopped:** review нашёл acceptance gap — `project_owner` есть в JSON но не выводится; `last_commit_iso` только в relative age, не абсолютной дате.
|
||||
**Next action:** TDD render + симметрично client-side board.js. См. `board-viewer-card-meta-fix.md`.
|
||||
**Branch:** master
|
||||
|
||||
---
|
||||
|
||||
## ⚪ [board-viewer-polish] — bundle of 6 minor/nitpick findings from review
|
||||
**Status:** ready
|
||||
**Where I stopped:** detailed list в task-файле; парсер comment, formatAge future-ts test, gitea-reader decisions-log clarification, filter status multi-select, docker healthcheck+stderr, parallel commit-iso.
|
||||
**Next action:** забирать items по одному. См. `board-viewer-polish.md`.
|
||||
**Branch:** master
|
||||
|
||||
---
|
||||
|
||||
43
.tasks/board-viewer-card-meta-fix.md
Normal file
43
.tasks/board-viewer-card-meta-fix.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# board-viewer-card-meta-fix
|
||||
|
||||
## Goal
|
||||
|
||||
Card meta сейчас содержит **title + project + age**. Acceptance criteria `board-viewer-html-render.md` строка 19-24 явно перечисляет 5 полей:
|
||||
|
||||
- title (труб 80 chars) ✅
|
||||
- project badge ✅
|
||||
- **owner (если есть) — pill** ❌ (поле `project_owner` есть в TaskRecord и JSON, но не выводится)
|
||||
- age (relative) ✅
|
||||
- **last-commit-marker — короткий hash или дата** ❌ (есть только relative age от `last_commit_iso`, абсолютной даты/хэша нет)
|
||||
|
||||
html-render таска закрылась без этих полей — gap. Не было замечено при self-review (потому и нужен independent reviewer).
|
||||
|
||||
## Key files
|
||||
|
||||
- `src/render.ts:111-127` — `renderCard()` (server-side первая рендер-проходка)
|
||||
- `static/board.js:76-89` — `renderCard()` (client-side rerender при toggle-grouping)
|
||||
- `tests/render.test.ts` — добавить assertions для двух новых полей
|
||||
- `static/board.css` — стиль для `.badge.owner` если нужно отличать визуально
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- Card showing `project_owner` as a pill (CSS class `.badge.owner`), скрыт если поле пустое.
|
||||
- Card showing last-commit-marker: minimum — ISO date `YYYY-MM-DD` (короткая дата, NOT relative). Hash недоступен из API без extra call → opt for date.
|
||||
- Возможность размещения: либо как третий meta-span после age, либо как tooltip на age (`title="<iso>"`); решение имплементера.
|
||||
- 2+ TDD tests:
|
||||
- card with `project_owner` shows owner pill containing the value
|
||||
- card with `last_commit_iso` shows date (e.g. `2026-05-22`) — separate from relative age
|
||||
- Обе ветки (server-side `src/render.ts` + client-side `static/board.js`) синхронны.
|
||||
|
||||
## Decisions log
|
||||
|
||||
- 2026-05-22: задача из review-чекпойнта; severity=major (acceptance gap, не self-replied).
|
||||
- Open: owner pill всегда показывать или только при variability (когда есть >1 owner в выборке)? — рекомендация: всегда показывать когда поле не null (нет смысла фильтровать на rendering этапе).
|
||||
|
||||
## Completed steps
|
||||
|
||||
- [ ] (фиксируется при выполнении)
|
||||
|
||||
## Notes
|
||||
|
||||
TDD obligatory — render логика, не visual. Тестируется через DOM-property assertions (как в `render.test.ts`).
|
||||
60
.tasks/board-viewer-polish.md
Normal file
60
.tasks/board-viewer-polish.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# board-viewer-polish
|
||||
|
||||
## Goal
|
||||
|
||||
Bundle of minor / nitpick findings from `board-viewer-review` checkpoint. Each — small, individually below the task-creation threshold; collectively worth doing in one sweep.
|
||||
|
||||
## Items
|
||||
|
||||
### M1. Document parser's `**Status:**` field neglect
|
||||
|
||||
- **Location:** `src/parser.ts` (in `parseOneBlock`)
|
||||
- **Problem:** `**Status:**` text field is matched by `FIELD_RE` but never stored in `StatusBlock` (emoji is SoT). Future maintainer reads parser and wonders why.
|
||||
- **Fix:** comment `// **Status:** text field intentionally ignored — emoji is canonical` near where it's matched, OR `delete fields['Status']` after parse to avoid the orphan field in local var. Choose the comment.
|
||||
|
||||
### M2. `formatAge` future-timestamp behavior is undocumented
|
||||
|
||||
- **Location:** `src/render.ts:31` + `static/board.js:49`
|
||||
- **Problem:** `Math.max(0, …)` silently clamps future ISO to "0m". With server-clock drift на VDS vs Gitea это маскирует ошибку синхронизации.
|
||||
- **Fix:** add one test asserting `formatAge(futureIso, now) === '0m'` to lock behavior, and add inline comment "// clamps to '0m' on future iso — see test".
|
||||
|
||||
### M3. `gitea-reader` acceptance "per-task без записи в STATUS.md (legacy)" is impossible by design
|
||||
|
||||
- **Location:** `.tasks/board-viewer-gitea-reader.md` Decisions log
|
||||
- **Problem:** Acceptance line 42 promises tests for "per-task без записи в STATUS.md (legacy)" case, but the reader iterates STATUS.md blocks only — orphan per-task files are invisible by design (matches spec: STATUS.md is the index).
|
||||
- **Fix:** append a decisions-log entry to `board-viewer-gitea-reader.md` clarifying this is intentional; STATUS.md is the entry point, orphan per-task files are out of scope.
|
||||
|
||||
### M4. Client filter doesn't match status in by-status mode; "multi-select по статусам" not implemented
|
||||
|
||||
- **Location:** `static/board.js:139-147` (`applyFilter`)
|
||||
- **Problem:** Filter reads `.badge.status` / `.badge.project` text from DOM. In by-status mode there's no status badge → typing "blocked" matches nothing. Также acceptance в `board-viewer-html-render.md:27` обещает multi-select по статусам — не реализован.
|
||||
- **Fix:** rebuild `applyFilter` to query the underlying `records` array (status always available regardless of view mode). Decide on multi-select: either ship a status-pill filter row, or amend acceptance criteria. Recommendation: add multi-select pills below the filter input — simple `<button data-status="…" class="status-filter">` toggle.
|
||||
|
||||
### M5. Build container failures show only `echo` output, no Docker healthcheck
|
||||
|
||||
- **Location:** `deploy/Dockerfile.build:14`
|
||||
- **Problem:** `... || echo 'render failed; will retry next tick'` swallows non-zero exit. Operator must `docker compose logs build` to notice. No Docker healthcheck signals unhealthy.
|
||||
- **Fix:** emit failure to stderr (`>&2 echo`), and add a `HEALTHCHECK` to Dockerfile that checks `[ -f /output/index.html ]` AND `[ $(date +%s) - $(stat -c %Y /output/index.html) -lt 600 ]` (file exists AND fresher than 10 min). Compose `web` service can `depends_on` health.
|
||||
|
||||
### M6. `getLatestCommitIso` called serially, N=80+ per tick
|
||||
|
||||
- **Location:** `src/reader.ts:36-37`
|
||||
- **Problem:** `for...of await` serializes 80+ HTTP calls. Within budget for now but a Gitea hiccup serializes through all of them.
|
||||
- **Fix:** parallelize per-repo or globally with `Promise.all(blocks.map(...))`. Cap concurrency at ~10 if politeness is a concern.
|
||||
|
||||
## Decisions log
|
||||
|
||||
- 2026-05-22: bundle создан промоушеном из review-чекпойнта; severity варьируется minor → nitpick; bundled, чтобы не плодить 6 микро-тасок.
|
||||
|
||||
## Completed steps
|
||||
|
||||
- [ ] M1: parser comment
|
||||
- [ ] M2: formatAge future-ts test + comment
|
||||
- [ ] M3: decisions-log entry in gitea-reader.md
|
||||
- [ ] M4: filter rebuild + status multi-select OR acceptance amendment
|
||||
- [ ] M5: stderr + Docker HEALTHCHECK
|
||||
- [ ] M6: parallelize commit-iso fetches
|
||||
|
||||
## Notes
|
||||
|
||||
Каждый item — TDD по тому, что есть testable. M1/M3 — comment/docs only ([skip-tdd: visual]). M2 — pure test. M4/M5/M6 — TDD logic.
|
||||
28
.tasks/board-viewer-readme-emoji-fix.md
Normal file
28
.tasks/board-viewer-readme-emoji-fix.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# board-viewer-readme-emoji-fix
|
||||
|
||||
## Goal
|
||||
|
||||
Fix stale emoji legend в `README.md`. README — первое, что видит человек открывая repo. Сейчас он указывает старый emoji-набор `⚪ 🟡 🟣 🔴 🟢` (с фиолетовым и красным=blocked), который был исправлен mid-stream на корректный `⚪ 🔴 🟡 🔵 🟢` (everywhere else в код-базе).
|
||||
|
||||
Найдено в review-checkpoint (`board-viewer-review`).
|
||||
|
||||
## Key files
|
||||
|
||||
- `README.md` строка 5 — "About" с emoji-словарём
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- README.md строка 5 содержит корректный emoji-словарь: `⚪ open / 🔴 in-progress / 🟡 paused / 🔵 blocked / 🟢 done`
|
||||
- Заодно — заполнить TBD блок "Quick start" одной командой: `npx vitest run` + `node --experimental-strip-types src/cli.ts <auth-toml-path>`
|
||||
|
||||
## Decisions log
|
||||
|
||||
- 2026-05-22: findings зафайлены в review-чекпойнте; severity=major (стартовое впечатление, рассинхрон со всем кодом).
|
||||
|
||||
## Completed steps
|
||||
|
||||
- [ ] (фиксируется при выполнении)
|
||||
|
||||
## Notes
|
||||
|
||||
Trivially small fix — `[skip-tdd: visual]` (docs).
|
||||
@@ -38,14 +38,22 @@ Code-review checkpoint для брейнсторма `board-viewer` (промо
|
||||
## Decisions log
|
||||
|
||||
- 2026-05-22: review-task создан промоушеном; status=blocked, blocker = все 4 импл-таски.
|
||||
- 2026-05-22: review выполнен subagent'ом (general-purpose, clean context). 43/43 тестов pass, TDD-immutability clean (no `[test-modify:]` markers needed — diffs append-only), secret hygiene OK (`02a14e` grep clean across `deploy/`). 2 Major findings + 6 minor/nitpick — зафайлены: `board-viewer-readme-emoji-fix`, `board-viewer-card-meta-fix`, `board-viewer-polish` (бандл).
|
||||
- 2026-05-22: findings зафайлены LOCAL в `.tasks/` (project-discipline Rule 1 override), не через `mcp__projects-meta__tasks_create` (это локальные таски, не cross-project).
|
||||
|
||||
## Open questions
|
||||
|
||||
- [ ] (заполняется ревьюером по ходу)
|
||||
- [x] (нет — все findings зафайлены)
|
||||
|
||||
## Completed steps
|
||||
|
||||
- [ ] (фиксируется при выполнении)
|
||||
- [x] спецификация прочитана subagent'ом
|
||||
- [x] `git log --oneline` сверен с acceptance criteria каждой импл-таски
|
||||
- [x] test suite прогнан (43/43 pass)
|
||||
- [x] design ↔ shipped contract проверен
|
||||
- [x] TDD-immutability audit (clean)
|
||||
- [x] secret hygiene grep (clean)
|
||||
- [x] findings зафайлены follow-up тасками
|
||||
|
||||
## Notes
|
||||
|
||||
|
||||
Reference in New Issue
Block a user