plan: rewrite for Wails GUI + full file/folder workflow

- Archive browser prototype as legacy (step 6)
- New steps 11-14: Wails GUI, Files/Folders, D&D, stabilization
- Steps 15+ paused until step 14 complete
- DokuWiki moved to contrib/plugins/ (optional)
- Full architecture: Wails bindings → Go core → vault+SQLite
- Detailed acceptance criteria for each step
This commit is contained in:
mirivlad 2026-05-31 12:10:58 +08:00
parent 752b1bb4b8
commit 537e8a126e
1 changed files with 230 additions and 336 deletions

View File

@ -1,4 +1,4 @@
# Верстак — Пошаговый план реализации
# Верстак — Пошаговый план разработки
## Принципы работы
@ -16,359 +16,246 @@
| 3 | Nodes Repository + CRUD + CLI Node | ✅ выполнен |
| 4 | Vault Files: Trash + File Service + CLI File | ✅ выполнен |
| 5 | Markdown Notes: Create/Read/Save + CLI Note | ✅ выполнен |
| 6 | Wails GUI MVP: Sidebar + Main Panel | ✅ выполнен (Go HTTP SPA) |
| 7 | Actions: Run URL/File/Command + GUI Tab | ✅ выполнен |
| 8 | Worklog: Entries + Report + GUI Tab | ✅ выполнен |
| 9 | FTS5 Search: Rebuild Index + GUI Search Bar | ✅ выполнен |
| 10 | Plugins System (Lua + Templates) | ✅ выполнен |
| 11 | Sync Server Skeleton | ⬜ не начат |
| 12 | Sync Client MVP | ⬜ не начат |
| 13 | Activity + File Scanner/Watcher | ⬜ не начат |
| 14 | TUI MVP (Bubble Tea) | ⬜ не начат |
| 15 | Integrity Check + Repair + Vault Restore | ⬜ не начат |
| 16 | Plugins System (Lua + Templates) | ⬜ не начат |
| 6 | GUI (browser prototype): Sidebar + Main Panel | ✅ выполнен |
| 7 | Actions + Worklog | ✅ выполнен |
| 8 | FTS5 Search | ✅ выполнен |
| 9 | Section assignment + Sidebar filtering | ✅ выполнен |
| 10 | Plugin Manager (discovery + templates) | ✅ выполнен |
| 11 | **Wails Desktop GUI** | ⬜ не начат |
| 12 | **Files/Folders full workflow** | ⬜ не начат |
| 13 | **Drag-and-drop** | ⬜ не начат |
| 14 | **MVP stabilization** | ⬜ не начат |
| 15 | Sync Server Skeleton | 🔒 приостановлен |
| 16 | Sync Client MVP | 🔒 приостановлен |
| 17 | Activity + File Scanner/Watcher | 🔒 приостановлен |
| 18 | TUI MVP (Bubble Tea) | 🔒 приостановлен |
| 19 | Integrity Check + Repair | 🔒 приостановлен |
| 20 | Plugins: Lua runtime | 🔒 приостановлен |
| 21 | DokuWiki Importer (plugin) | 🔒 приостановлен |
> 🔒 = **PAUSED** — не начинать до завершения шага 14 (MVP stabilization).
---
## ШАГ 1 — Git Init + Skeleton
## Выполненные шаги (1-10)
**Цель:** репозиторий создан, пустая структура, "hello world" билдится.
**Acceptance:**
- `go build ./...` проходит
- `go test ./...` проходит
- `verstak --version` выводит версию
- Повторный init безопасен
**Действия:**
- git init, .gitignore (Go, Wails)
- `go mod init verstak`
- Структура: `cmd/verstak/`, `internal/core/`, `migrations/`
- `cmd/verstak/main.go`: --version flag
### ШАГ 1 — Git Init + Skeleton
- go module `verstak`, структура cmd/internal/migrations
- CLI `verstak --version`
- README.md
**Commit:** `step 1: skeleton`
### ШАГ 2 — Init + SQLite
- storage.go: DB wrapper, migration runner
- vault.go: Init() создаёт .verstak/ + index.db
- config.go: YAML config
### ШАГ 3 — Nodes Repository
- Node struct + CRUD (Create, Get, ListChildren, ListRoots, UpdateTitle, Move, SoftDelete)
- Meta KV + tests
### ШАГ 4 — Files
- FileService: AddExternal, CopyIntoVault, Get, ListByNode, MarkMissing, DeleteToTrash, Open
- file_test.go: 5 tests
### ШАГ 5 — Notes
- NoteService: Create, Read, Save (с backup), Delete
- note_test.go: 3 tests
### ШАГ 6 — GUI (browser prototype)
- Go HTTP SPA на случайном порту
- Sidebar tree + разделы (Сегодня, Неразобранное, Клиенты, Проекты...)
- Dashboard дела + вкладки (Обзор, Заметки, Файлы, Действия, Журнал, Активность)
- Модальное окно "+ Добавить" с выбором типа
- Поиск по корневым нодам
- **Это legacy prototype — не развивать как основной GUI**
### ШАГ 7 — Actions + Worklog
- ActionService: Create, Get, ListByNode, Delete, Run (open_url/file/folder, run_command)
- WorklogService: Add, Update, ListByNode, Delete, SumMinutes, Report
- CLI: `action add/list/run/delete`, `log add/list/report`
- GUI вкладки с кнопками действий и журналом работ
### ШАГ 8 — FTS5 Search
- SearchService: Index, Remove, Rebuild, Search (FTS5 MATCH)
- FTS5 virtual table создаётся лениво (работает с/без FTS5)
- Fallback на LIKE по заголовкам нод
- CLI: `verstak index rebuild`
- GUI search bar
### ШАГ 9 — Section assignment
- Колонка `section` в nodes (clients/projects/recipes/documents/archive/inbox)
- Фильтрация разделов по `?section=` в API
- Root-ноды без section → inbox
### ШАГ 10 — Plugin Manager
- Discovery: `.verstak/plugins/<name>/plugin.json`
- Enable/disable, templates → pre-filled node trees
- Built-in шаблон "Клиент" (Overview + Документы/Переписка/Скриншоты)
- Template selector в модалке создания дела
- POST /api/nodes/from-template
- CLI: `plugin list/enable/disable/templates`
- Lua runtime — stub (placeholder)
---
## ШАГ 2 — Init + SQLite + First Migration
## Текущий этап: ШАГ 11 — Wails Desktop GUI
**Цель:** `verstak init --vault ./test` создаёт vault с index.db.
**Целевой commit:** `gui/wails-file-workflow`
**Acceptance:**
- `go test ./...` проходит
- init создаёт `.verstak/index.db`
- повторный init безопасен
Архитектура:
**Действия:**
- migration runner (cmd + SQL migrations/)
- миграция 001_init.sql (таблица nodes)
- `_ "github.com/mattn/go-sqlite3"` или modernc driver
- CLI `init`: vault dir + `.verstak/` + `index.db`
```
┌─────────────────────────────────────────────────┐
│ Frontend (Wails) │
│ frontend/src/ │
│ App.svelte │
│ components/Sidebar, TopBar, CaseView, ... │
│ stores/selection, nodes, files, ui │
│ styles/theme.css │
└──────────────────┬──────────────────────────────┘
│ Wails bindings
┌──────────────────▼──────────────────────────────┐
│ Go Core (internal/core/) │
│ nodes, vault, storage, notes, files, │
│ actions, worklog, search, plugins │
└──────────────────┬──────────────────────────────┘
┌──────────────────▼──────────────────────────────┐
│ Vault filesystem + SQLite │
└─────────────────────────────────────────────────┘
```
**Commit:** `step 2: init + sqlite + first migration`
### Действия
1. Создать Wails app skeleton (`wails init`)
2. Структура frontend/ — Svelte/Vue/vanilla TS
3. Backend bindings — методы Wails над core services
4. Перенести текущий UI shell из inline HTML в frontend
5. Оставить текущий `internal/gui/` как legacy (не удалять, но не развивать)
### Backend bindings (минимум)
```go
// Nodes
ListSections() ([]SectionDTO, error)
ListNodes(section string) ([]NodeDTO, error)
GetNodeDetail(nodeID string) (NodeDetailDTO, error)
CreateNode(parentID, section, typ, title string) (NodeDTO, error)
FromTemplate(parentID, section, typ, title, template string) (NodeDTO, error)
DeleteNode(id string) error
MoveNode(id, parentID string) error
// Notes
CreateNote(parentID, title string) (NodeDTO, error)
ReadNote(noteID string) (string, error)
SaveNote(noteID, content string) error
// Files
ListFiles(nodeID string) ([]FileDTO, error)
AddPathCopy(nodeID, sourcePath string) ([]NodeDTO, error) // файл или папка
AddPathLink(nodeID, sourcePath string) ([]NodeDTO, error)
DeleteFileOrFolder(id string) error
OpenFile(id string) error
OpenFolder(id string) error
PickFile() (string, error)
PickDirectory() (string, error)
// Actions/Worklog/Search
ListActions(nodeID string) ([]ActionDTO, error)
RunAction(id string) error
CreateWorklog(nodeID, summary string, minutes int) (WorklogDTO, error)
Search(query string) ([]SearchResultDTO, error)
```
---
## ШАГ 3 — Nodes Repository + CRUD + CLI Node
## ШАГ 12 — Files/Folders full workflow
**Цель:** можно создать/прочитать/переместить/удалить дело через CLI.
### Core service extensions
**Acceptance:**
- nodes + node_meta таблицы
- NodeRepository: Create, Get, ListChildren, UpdateTitle, Move, SoftDelete
- CLI: `node create`, `node list`, `node move`, `node delete`
- unit tests проходят
Расширить `files.Service`:
**Действия:**
- Полная схема nodes (id, parent_id, type, title, slug, path, sort_order, created_at, updated_at, deleted_at, revision, device_id)
- node_meta (node_id, key, value)
- Node struct + Repository
- UUID вместо auto-increment
- Soft delete (deleted_at)
- безопасный slug для path
- Tests: in-memory SQLite
```go
AddPathCopy(nodeID string, sourcePath string) ([]Node, error)
AddPathLink(nodeID string, sourcePath string) ([]Node, error)
```
**Commit:** `step 3: nodes repository + CRUD`
Логика:
- `os.Stat(sourcePath)` → если директория → рекурсивный обход
- Каждый файл → File node + file record
- Каждая папка → Folder node
- Структура сохраняется через parent_id
### Folder model
Папка = node type `folder` (не file record с mime=directory).
При импорте `romashka-docs/`:
```
Folder node: romashka-docs (type=folder)
File node: dogovor.docx (type=file)
Folder node: screenshots (type=folder)
File node: error.png (type=file)
```
### Name conflict resolution
Если в target уже есть `docs`:
```
docs
docs (2)
docs (3)
```
### Safety checks
При добавлении папки показать summary:
- количество файлов/папок
- общий размер
- предупреждение если > 1000 файлов, > 1 GB, содержит `.git`/`node_modules`/`.cache`
### Trash
- Soft delete node + children
- Vault files → `.verstak/trash`
- External files — только удалить связь
- Не `rm -rf`
### Tests
1. Copy single file → vault, record created, source intact
2. Link single file → no copy, external path saved
3. Copy folder → tree created, files in vault
4. Link folder → node created, no content copied
5. Delete vault file → soft-deleted, file in trash
6. Delete vault folder → children soft-deleted
7. Name conflict → no overwrite, safe suffix
8. Open file → mocked opener (no real app launch)
---
## ШАГ 4 — Vault Files: Trash + File Service + CLI File
## ШАГ 13 — Drag-and-drop
**Цель:** можно добавить файл в дело, открыть системным приложением, удалить в trash.
### External D&D
**Acceptance:**
- `.verstak/trash/` создаётся при init
- copy file into vault работает
- open with system app работает
- delete-to-trash работает
- тесты проходят
Drop target: активное дело / вкладка Файлы / Неразобранное.
**Действия:**
- Таблица files (id, node_id, filename, path, storage_mode, size, sha256, mime, ...)
- VaultService: CopyFile, LinkExternal, OpenFile, DeleteToTrash, RestoreFromTrash
- CLI: `file add`, `file list`, `file open`, `file trash`
**Commit:** `step 4: vault files + trash + CLI`
После drop → диалог:
```
Добавить в "ООО Ромашка / Сайт"
Файлов: 3, Папок: 1, 240 MB
[Скопировать] [Переместить] [Привязать] [Отмена]
```
---
## ШАГ 5 — Markdown Notes: Create/Read/Save + CLI Note
## ШАГ 14 — MVP stabilization
**Цель:** можно создать заметку, писать в неё, читать обратно.
**Acceptance:**
- type "note" для nodes
- создать .md файл в vault
- save делает backup старой версии
- тесты проходят
**Действия:**
- Таблица notes (node_id, file_id, format, original_format, encrypted)
- NoteService: CreateNote, ReadNote, SaveNote (с backup)
- CLI: `note create`, `note read`, `note write`
- Backup старой версии перед перезаписью
**Commit:** `step 5: markdown notes`
---
## ШАГ 6 — Wails GUI MVP
**Цель:** GUI запускается, видно дерево дел, можно создать дело и заметку.
**Acceptance:**
- sidebar tree показывает дела
- create node работает
- markdown textarea editor с save
- file list + add file + open file
- главный пользовательский поток работает
**Действия:**
- Wails app init (Go backend + Svelte/Vue)
- Backend bindings: NodeService, VaultService, NoteService
- Frontend: sidebar tree, main panel, modals, markdown editor
- Поток: дело → заметка → файл → открыть файл
**Commit:** `step 6: Wails GUI MVP`
---
## ШАГ 7 — Actions
**Цель:** можно создать кнопку "Открыть сайт", нажать, сайт открылся.
**Acceptance:**
- open_url, open_file, open_folder, run_command
- confirm_required диалог
- action log
- GUI вкладка "Действия"
**Действия:**
- Таблица actions
- ActionService: Run с confirm, exec.Command БЕЗ shell, args массивом
- CLI: `action add`, `action list`, `action run`
- GUI: вкладка с кнопками
**Commit:** `step 7: actions`
---
## ШАГ 8 — Worklog
**Цель:** можно записать "3ч обновил витрину", скопировать отчёт.
**Acceptance:**
- add/edit/delete entry
- approximate minutes + billable flag
- copy report копирует в буфер
- GUI вкладка "Журнал"
**Действия:**
- Таблица worklog_entries
- WorklogService: Add, Edit, Delete, CopyReport
- CLI: `worklog add`, `worklog list`, `worklog report`
- GUI: вкладка журнал + кнопка copy report
**Commit:** `step 8: worklog`
---
## ШАГ 9 — FTS5 Search
**Цель:** можно найти "витрину" по заметкам, файлам, журналу.
**Acceptance:**
- `verstak index rebuild` перестраивает индекс
- поиск по node titles, note content, filenames, worklog summaries
- GUI search bar + результаты с type/path
**Действия:**
- Таблица search_index (FTS5): node_id, title, content, path, tags, type
- Триггеры для автоматического обновления или manual rebuild
- SearchService: RebuildIndex, Search(query)
- CLI: `index rebuild`
- GUI: search bar в header
**Commit:** `step 9: FTS5 search`
---
## ШАГ 10 — Система плагинов (Lua + шаблоны дел)
**Цель:** можно положить Lua-скрипт в `.verstak/plugins/` — и он работает.
Без перекомпиляции программы.
**Acceptance:**
- `.verstak/plugins/<name>/plugin.json` — мета
- `main.lua` — загрузка через gopher-lua
- `on_init`, `on_vault_open`, `on_node_create` хуки
- `verstak.node.register_type()` — новые типы дел
- `verstak.http.route()` — API для GUI
- шаблоны дела (JSON) → предзаполненное дерево
- песочница: нет io/os.execute, только API
- CLI: `verstak plugin list / install / enable`
- DokuWiki импортер — пример плагина в `contrib/plugins/importer-dokuwiki/`
**Действия:**
- `internal/core/plugins/manager.go` — сканирование, загрузка, валидация
- Lua runtime (gopher-lua) с песочницей
- Plugin API: node, config, activity, http, ui, vault
- Миграции плагинов (SQL)
- Реестр типов дел → GUI рендерит разные карточки
- CLI: plugin list/install/enable
- Базовый шаблон дела (client.json)
- Пример плагина: DokuWiki importerв `contrib/`
**Commit:** `step 10: plugins system`
---
## ШАГ 11 — Sync Server Skeleton
**Цель:** verstak-server отвечает на /health, /sync/push, /sync/pull, /blobs.
**Acceptance:**
- HTTP server на отдельном порту
- API key auth
- blob storage by sha256
- GET /health, POST /sync/push, POST /sync/pull, POST /blobs/upload, GET /blobs/{sha256}
**Действия:**
- `cmd/verstak-server/main.go`
- SQLite server db
- Push/pull operations endpoints
- Blob upload/download with sha256 naming
**Commit:** `step 11: sync server skeleton`
---
## ШАГ 12 — Sync Client MVP
**Цель:** `verstak sync` отправляет локальные операции на сервер и получает обратно.
**Acceptance:**
- sync_ops таблица
- операции создаются при каждом изменении
- push local ops + pull remote ops
- upload/download blobs
- conflict copy при неуверенности
**Действия:**
- Таблица sync_ops (опционально добавить триггеры в repository)
- SyncClient: Push, Pull, UploadBlob, DownloadBlob
- CLI: `verstak sync`
- Server URL + API key в .verstak/config
**Commit:** `step 12: sync client MVP`
---
## ШАГ 13 — Activity + File Scanner/Watcher
**Цель:** фиксируется открытие/редактирование, scanner видит новые файлы.
**Acceptance:**
- activity_events таблица
- scanner сравнивает реальность с SQLite
- watcher (fsnotify) ускоряет обнаружение
- экран "Активность" с группировкой по делу
- можно создать worklog из events
**Действия:**
- Таблица activity_events
- Запись событий из nodes/notes/files/actions
- Snapshot scanner (источник правды)
- fsnotify watcher (ускоритель)
- CLI: `scan`, `activity list`
- GUI: экран "Активность"
**Commit:** `step 13: activity + scanner/watcher`
---
## ШАГ 14 — TUI MVP (Bubble Tea)
**Цель:** быстрый поиск дела, добавление worklog, запуск action.
**Acceptance:**
- fuzzy search tree
- open node
- add worklog
- run action
- sync now
**Действия:**
- `cmd/verstak-tui/main.go` с Bubble Tea
- Модели: search, node view, worklog form, action runner
- Не повторяет весь GUI — только быстрые действия
**Commit:** `step 14: TUI MVP`
---
## ШАГ 15 — Integrity Check + Repair + Vault Restore
**Цель:** `verstak vault check` находит проблемы, repair чинит, restore восстанавливает.
**Acceptance:**
- check: missing files, orphan files, SQLite references, hash mismatch
- repair: устраняет найденные проблемы
- restore с сервера восстанавливает vault
**Действия:**
- CLI: `vault check` — сканирует и отчитывается
- CLI: `vault repair` — чинит найденное
- CLI: `restore --server <url> --api-key <key> --target <path>`
**Commit:** `step 15: integrity + restore`
---
## ШАГ 16 — Система плагинов (Lua + шаблоны дел)
**Цель:** можно положить Lua-скрипт в `.verstak/plugins/` — и он работает.
**Acceptance:**
- `.verstak/plugins/<name>/plugin.json` — мета
- `main.lua` — загрузка через gopher-lua
- `on_init`, `on_vault_open`, `on_node_create` хуки
- `verstak.node.register_type()` — новые типы дел
- `verstak.http.route()` — API для GUI
- шаблоны дела (JSON) → предзаполненное дерево
- CLI: `verstak plugin list / install / enable`
**Действия:**
- `internal/core/plugins/manager.go` — сканирование, загрузка, валидация
- Lua runtime (gopher-lua) с песочницей
- Plugin API: node, config, activity, http, ui, vault
- Миграции плагинов (SQL)
- Реестр типов дел → GUI рендерит разные карточки
- CLI: plugin list/install/enable
- Базовый шаблон дела (client.json)
**Commit:** `step 10: plugins system`
- Smoke tests базовых сценариев
- Проверка: дело → заметка → файл → папка → trash → перезапуск
- go test ./... pass
- Обновление документации
- Остановка перед следующими фичами
---
@ -382,10 +269,19 @@ verstak/
cmd/
verstak/ # CLI
verstak-gui/ # Wails GUI
verstak-gui/ # Wails GUI main
verstak-tui/ # Bubble Tea TUI
verstak-server/ # Sync server
frontend/ # Wails frontend
package.json
wails.json
src/
App.svelte
components/
stores/
styles/
internal/
core/
nodes/
@ -400,9 +296,11 @@ verstak/
sync/
security/
config/
plugins/
plugins/ # manager, lua (stub)
frontend/ # Wails frontend (Svelte/Vue)
contrib/
plugins/
importer-dokuwiki/
migrations/
001_init.sql
@ -411,15 +309,11 @@ verstak/
004_add_notes.sql
005_add_actions.sql
006_add_worklog.sql
007_add_activity.sql
008_add_fts.sql
009_add_sync.sql
```
## RAID (Risks, Assumptions, Issues, Dependencies)
## RAID
- **Критично:** Wails v3 может быть нестабилен — проверить перед шагом 6
- **Критично:** go-sqlite3 нужен cgo; modernc — чистый Go, выбрать до шага 2
- **Зависимость:** Шаги 12 (sync client) зависят от 11 (server)
- **Зависимость:** Шаг 6 (GUI) лучше откладывать до стабильности core
- **Риск:** Svelte/Vue фронтенд потребует node/npm — подготовить
- **Критично:** Wails требует Node.js для frontend-сборки
- **Критично:** go-sqlite3 + cgo; gcc уже установлен
- **Зависимость:** Steps 15+ ждут завершения step 14
- **Риск:** Wails v3 может быть нестабилен — проверить перед шагом 11