feat: tasks workflow

This commit is contained in:
2026-07-13 16:00:25 +05:00
parent 9705bac7af
commit ce69209820
15 changed files with 559 additions and 31 deletions
+93 -25
View File
@@ -6,6 +6,7 @@
```markdown
---
id: "..."
title: "Пофиксить баг логина"
status: todo # todo | in-progress | done | cancelled
priority: high # low | medium | high | critical
@@ -21,7 +22,7 @@ updated: 2026-07-12T10:00:00Z
**Структура папок:**
- `.vscode/tasks/` — проектные задачи
- `~/project-tasks/` — глобальные задачи (настраивается)
- глобальная папка — настраивается (`projectTasks.globalPath`)
Оба пути настраиваются через VS Code settings.
@@ -29,50 +30,117 @@ updated: 2026-07-12T10:00:00Z
Через **Custom Editor** + **WebView**:
1. **Activity Bar** своя вкладка с Task Dashboard
1. **Activity Bar** — вкладка Project Tasks
2. **Task Dashboard** — WebView в editor area со split layout:
- Левая панель — список задач с фильтрацией/группировкой
- Правая панель — содержимое выбранной задачи (редактируемый markdown)
3. **TreeView в Explorer** — быстрый просмотр
3. **TreeView** — быстрый просмотр по статусу
## Архитектура кода
Актуальная раскладка (после рефакторинга портов/адаптеров):
```txt
src/
├── extension.ts # Активация, регистрация
├── extension.ts # composition root (DI, register)
├── ports.ts # IFileSystem, ITaskRepository, IConfigProvider
├── error.ts # AppError + factories (единый каталог ошибок)
├── model/task.ts
├── storage/
│ ├── taskStore.ts # CRUD для .task.md (gray-matter парсинг)
── configStore.ts # Настройки
├── model/
│ └── task.ts # Интерфейс Task + типы
├── views/
│ ├── taskTreeProvider.ts # TreeView в sidebar
│ ├── taskListProvider.ts # Data provider для WebView
│ └── taskDashboardPanel.ts # WebView split layout
├── commands/
│ ├── FsTaskRepository.ts
── NodeFileSystem.ts
│ └── VscodeConfigProvider.ts
├── commands/ # use-cases без vscode UI
│ ├── createTask.ts
│ ├── openTask.ts
│ ├── deleteTask.ts
│ └── changeStatus.ts
├── views/
│ └── taskTreeProvider.ts # (+ dashboard later)
└── utils/
├── uuid.ts
└── markdown.ts
└── markdown.ts # parse/serialize frontmatter
tests/helpers/InMemoryFileSystem.ts
```
UI (input box, quick pick, open editor) — тонкие адаптеры; бизнес-логика в
use-cases + `ITaskRepository`. Ошибки — `AppError` из `error.ts`.
## План реализации
| Фаза | Что делаем |
| ------------------------ | -------------------------------------------------------------- |
| **1. Scaffold** | `yo code`, TypeScript, настройка package.json |
| **2. Storage** | TaskStore — чтение `.task.md`, парсинг через gray-matter, CRUD |
| **3. TreeView** | Боковая панель со списком задач по статусу |
| **4. Команды** | createTask, deleteTask, changeStatus, openTask |
| **5. Task Dashboard** | WebView split layout в editor area |
| **6. Глобальные задачи** | Второй storage (глобальная папка) |
| **7. Kanban** | Drag-n-drop доска |
| **8. Публикация** | vsce publish |
| Фаза | Что делаем |
| ------------------------ | ---------------------------------------------------------------------- |
| **1. Scaffold** | Extension, TypeScript, сборка, package.json |
| **2. Storage** | CRUD `.task.md`, парсинг frontmatter, unit-тесты storage |
| **3. TreeView** | sidebar по статусу, file watcher |
| **4. Команды** | createTask, deleteTask, changeStatus, openTask (use-cases → wiring UI) |
| **5. Task Dashboard** | WebView split layout |
| **6. Глобальные задачи** | использование globalPath |
| **7. Kanban** | drag-n-drop |
| **8. Публикация** | vsce publish |
### Фаза 4 — команды (use-cases)
| Команда | Поведение |
| -------------- | -------------------------------------------------------------- |
| `createTask` | title + folder → defaults todo/medium; empty title / no folder |
| `deleteTask` | folder + id → delete; not found |
| `changeStatus` | folder + id + status → update; not found |
| `openTask` | folder + id → path + task для editor; not found |
## Зависимости
- `gray-matter`парсинг YAML frontmatter
- `front-matter`разбор YAML frontmatter (body + attributes)
- `js-yaml` — сериализация frontmatter обратно в YAML (`dump`)
- `uuid` — генерация ID
- `neverthrow``Result` / `ResultAsync` для use-cases
- `vitest` / `eslint` — dev
## История изменений (решения, не чеклист)
Краткая летопись смен относительно **изначального** наброска плана. Детали
рефакторинга storage/тестов — в архиве `docs/REFACTOR-AND-TEST.md` (документ
закрыт, не ведём).
### Изначальный набросок (v0)
- Парсинг: **`gray-matter`**
- Storage: `taskStore.ts` (CRUD), `configStore.ts` (settings)
- Сборка/скелет: `yo code`-ориентированный scaffold
- Дерево модулей: storage + views (tree/list/dashboard) + commands + utils
### Рефакторинг storage / чистая архитектура
- `taskStore` / `configStore`**порты** (`IFileSystem`, `ITaskRepository`,
`IConfigProvider`) и адаптеры:
- `FsTaskRepository`, `NodeFileSystem`, `VscodeConfigProvider`
- `extension.ts` — composition root (DI), tree зависит от портов
- Unit-тесты: Vitest, colocation, `InMemoryFileSystem` в `tests/helpers/`
### `gray-matter` → `front-matter` + `js-yaml`
- **Было в плане:** один пакет `gray-matter` на parse (+ stringify при
необходимости).
- **Стало:** `front-matter` для чтения attributes/body; `js-yaml` (`dump`) для
записи frontmatter в `serializeTask`.
- **Зачем:** `gray-matter` даёт лишние возможности парсинга (eval для JS и
прочая «магия»), которые для задач не нужны; Vite на eval ругается, с точки
зрения безопасности это нежелательно. Поэтому parse через `front-matter`,
serialize через `js-yaml` (`dump`). Формат файла тот же: Markdown + YAML
frontmatter.
### neverthrow + `AppError`
- Use-cases возвращают `ResultAsync<T, AppError>` вместо кастомных
`{ ok, reason }`.
- Каталог ошибок: `src/error.ts` (`AppErrorCode`, factories `AppError.noFolder()`
и т.д.).
### Прочее относительно v0
- Сборка: Vite (extension bundle), не классический `tsc`-only из yo code
- В модели/файле задачи зафиксирован **`id`** в frontmatter (нужен для
list/get/update/delete)
- Фаза 4: use-cases в `src/commands/*` тестируются без vscode; UI — отдельные
адаптеры