docs: initial platform architecture docs
This commit is contained in:
parent
a1e8248673
commit
dbd7264cd9
|
|
@ -0,0 +1,36 @@
|
||||||
|
# Verstak Platform Docs
|
||||||
|
|
||||||
|
Этот комплект фиксирует новый архитектурный курс Верстака: не монолитное приложение с набором встроенных экранов, а local-first платформа рабочего vault, где пользовательские функции подключаются динамическими плагинами.
|
||||||
|
|
||||||
|
Исходная идея Верстака сохраняется:
|
||||||
|
|
||||||
|
> Верстак - локальная рабочая среда, где по каждому клиенту, проекту или делу собраны файлы, заметки, документы, ссылки, действия, журнал и история работы.
|
||||||
|
|
||||||
|
Меняется внутреннее устройство. Заметки, файловый менеджер, редакторы, предпросмотр, журнал, активность, браузерный inbox и подобные части больше не считаются внутренними разделами одного приложения. Они становятся плагинами, которые подключаются к платформе через capability registry, contribution points и permissions.
|
||||||
|
|
||||||
|
## Документы
|
||||||
|
|
||||||
|
- [01_Product_Vision.md](01_Product_Vision.md) - продуктовая идея, что остается неизменным и зачем Верстак нужен.
|
||||||
|
- [02_Platform_Architecture.md](02_Platform_Architecture.md) - архитектура ядра, runtime, vault, UI shell и plugin host.
|
||||||
|
- [03_Repositories.md](03_Repositories.md) - разбиение на репозитории и назначение каждого.
|
||||||
|
- [04_Plugin_System.md](04_Plugin_System.md) - динамические плагины, manifest, lifecycle, capabilities, settings, permissions.
|
||||||
|
- [05_Official_Plugins.md](05_Official_Plugins.md) - состав официальных плагинов и их зависимости через capabilities.
|
||||||
|
- [06_Migration_Strategy.md](06_Migration_Strategy.md) - как переходить от текущего приложения к платформе без потери смысла.
|
||||||
|
- [AGENTS.md](AGENTS.md) - инструкция для coding agents, чтобы они не возвращали проект к монолиту.
|
||||||
|
|
||||||
|
## Главный архитектурный инвариант
|
||||||
|
|
||||||
|
Core не знает о конкретных функциях вроде "заметки", "файловый менеджер" или "markdown editor". Core знает о:
|
||||||
|
|
||||||
|
- vault;
|
||||||
|
- plugin runtime;
|
||||||
|
- capability registry;
|
||||||
|
- contribution points;
|
||||||
|
- permissions;
|
||||||
|
- settings registry;
|
||||||
|
- event bus;
|
||||||
|
- storage API;
|
||||||
|
- UI shell.
|
||||||
|
|
||||||
|
Все рабочие инструменты поставляются плагинами. Даже официальные плагины должны жить по тем же правилам, что и будущие сторонние.
|
||||||
|
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
# Verstak - Product Vision
|
||||||
|
|
||||||
|
## 1. Зачем существует Верстак
|
||||||
|
|
||||||
|
Верстак нужен не как еще один заметочник, файловый менеджер, CRM или таск-трекер. Его задача - удерживать рабочий контекст вокруг дела.
|
||||||
|
|
||||||
|
Дело может быть клиентом, проектом, ремонтом, сервером, статьей, устройством, заказом, учебным курсом или личной разработкой. В обычной жизни информация по делу расползается по папкам, wiki, заметкам, истории терминала, чатам, браузеру, password manager, таблицам и памяти. Через месяц трудно восстановить, что было сделано, где актуальный файл, какой сервер относится к какому клиенту, почему была принята та или иная настройка.
|
||||||
|
|
||||||
|
Верстак собирает это в один локальный vault.
|
||||||
|
|
||||||
|
## 2. Главная формула
|
||||||
|
|
||||||
|
> Верстак - local-first рабочий vault вокруг дел.
|
||||||
|
|
||||||
|
Внутри дела живут:
|
||||||
|
|
||||||
|
- заметки;
|
||||||
|
- файлы и документы;
|
||||||
|
- ссылки;
|
||||||
|
- действия;
|
||||||
|
- журнал работ;
|
||||||
|
- история активности;
|
||||||
|
- отправленные из браузера материалы;
|
||||||
|
- клиентские доступы и секреты;
|
||||||
|
- контекст, который нужен, чтобы вернуться к работе через месяц или год.
|
||||||
|
|
||||||
|
## 3. Что меняется в платформенной версии
|
||||||
|
|
||||||
|
Раньше Верстак можно было описать как приложение:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Верстак = дерево дел + заметки + файлы + редактор + журнал + синхронизация
|
||||||
|
```
|
||||||
|
|
||||||
|
Новая модель:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Верстак = core platform + vault + plugin runtime + official plugins
|
||||||
|
```
|
||||||
|
|
||||||
|
Это важно не ради архитектурной красоты. Это защищает проект от превращения в жесткий комбайн, где каждая новая функция врастает в `App.svelte`, backend methods и общий state.
|
||||||
|
|
||||||
|
## 4. Что должно остаться неизменным
|
||||||
|
|
||||||
|
- Local-first: пользовательские данные живут локально и остаются доступными без облака.
|
||||||
|
- Vault остается читаемым человеком: файлы и заметки не должны превращаться в непрозрачную базу.
|
||||||
|
- Главное понятие - дело, а не задача.
|
||||||
|
- Верстак не становится SaaS, CRM или корпоративной системой.
|
||||||
|
- Синхронизация - дополнение, а не источник правды.
|
||||||
|
- Плагины расширяют рабочую среду, но не ломают базовую доступность данных.
|
||||||
|
- Пользователь должен понимать, где лежат его данные и что с ними происходит.
|
||||||
|
|
||||||
|
## 5. Что не входит в ядро
|
||||||
|
|
||||||
|
В ядро не входят:
|
||||||
|
|
||||||
|
- markdown editor;
|
||||||
|
- file manager;
|
||||||
|
- image/pdf preview;
|
||||||
|
- notes workflow;
|
||||||
|
- activity reconstruction;
|
||||||
|
- journal UI;
|
||||||
|
- browser inbox;
|
||||||
|
- secrets manager;
|
||||||
|
- importer/exporter;
|
||||||
|
- AI assistant;
|
||||||
|
- kanban/calendar/client-specific screens.
|
||||||
|
|
||||||
|
Все это должно быть плагинами.
|
||||||
|
|
||||||
|
## 6. Продуктовая цель платформы
|
||||||
|
|
||||||
|
Платформенная архитектура нужна, чтобы Верстак мог расти не как один большой экран, а как рабочий стол мастера:
|
||||||
|
|
||||||
|
- один пользователь может использовать только файлы, заметки и журнал;
|
||||||
|
- другой добавит браузерный inbox и activity recovery;
|
||||||
|
- третий подключит секреты, SSH, серверные профили и клиентские шаблоны;
|
||||||
|
- четвертый заменит markdown editor на другой;
|
||||||
|
- пятый поставит два редактора и будет выбирать нужный.
|
||||||
|
|
||||||
|
Верстак остается одним рабочим местом, но инструменты на этом месте можно менять.
|
||||||
|
|
||||||
|
|
@ -0,0 +1,277 @@
|
||||||
|
# Verstak Platform Architecture
|
||||||
|
|
||||||
|
## 1. Общая схема
|
||||||
|
|
||||||
|
```text
|
||||||
|
+----------------------+
|
||||||
|
| UI Shell |
|
||||||
|
| windows, layout, |
|
||||||
|
| command palette, |
|
||||||
|
| settings, toasts |
|
||||||
|
+----------+-----------+
|
||||||
|
|
|
||||||
|
+----------v-----------+
|
||||||
|
| Core Platform |
|
||||||
|
| plugin manager, |
|
||||||
|
| capabilities, |
|
||||||
|
| permissions, events |
|
||||||
|
+----------+-----------+
|
||||||
|
|
|
||||||
|
+-------------------+-------------------+
|
||||||
|
| | |
|
||||||
|
+-------v--------+ +-------v--------+ +-------v--------+
|
||||||
|
| Local Vault | | Storage API | | Sync Boundary |
|
||||||
|
| files, notes, | | SQLite, index, | | client adapter |
|
||||||
|
| assets, trash | | migrations | | not core truth |
|
||||||
|
+-------+--------+ +-------+--------+ +-------+--------+
|
||||||
|
| | |
|
||||||
|
+-------------------+-------------------+
|
||||||
|
|
|
||||||
|
+----------v-----------+
|
||||||
|
| Dynamic Plugins |
|
||||||
|
| official and third |
|
||||||
|
| party packages |
|
||||||
|
+----------------------+
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. Core Platform
|
||||||
|
|
||||||
|
Core Platform - минимальное ядро приложения. Оно не содержит бизнес-функции пользователя. Его задача - дать среду, в которую плагины безопасно подключают рабочие инструменты.
|
||||||
|
|
||||||
|
Core отвечает за:
|
||||||
|
|
||||||
|
- запуск приложения;
|
||||||
|
- открытие и проверку vault;
|
||||||
|
- загрузку и выгрузку плагинов;
|
||||||
|
- enable/disable состояние плагинов;
|
||||||
|
- capability registry;
|
||||||
|
- contribution points;
|
||||||
|
- settings registry;
|
||||||
|
- permissions;
|
||||||
|
- event bus;
|
||||||
|
- storage API;
|
||||||
|
- vault file API;
|
||||||
|
- command registry;
|
||||||
|
- diagnostics;
|
||||||
|
- sync boundary.
|
||||||
|
|
||||||
|
Core не должен импортировать конкретные плагины как обязательные модули.
|
||||||
|
|
||||||
|
## 3. UI Shell
|
||||||
|
|
||||||
|
UI Shell - общий интерфейс платформы:
|
||||||
|
|
||||||
|
- главное окно;
|
||||||
|
- навигация;
|
||||||
|
- вкладки и панели;
|
||||||
|
- command palette;
|
||||||
|
- global search entry point;
|
||||||
|
- settings window;
|
||||||
|
- plugin manager window;
|
||||||
|
- dialogs/toasts;
|
||||||
|
- error boundary для plugin UI.
|
||||||
|
|
||||||
|
UI Shell не знает, что такое notes editor или file preview как конкретная реализация. Он знает contribution points:
|
||||||
|
|
||||||
|
- sidebar items;
|
||||||
|
- main views;
|
||||||
|
- case tabs;
|
||||||
|
- file actions;
|
||||||
|
- note actions;
|
||||||
|
- context menu entries;
|
||||||
|
- settings panels;
|
||||||
|
- command palette commands;
|
||||||
|
- status bar items;
|
||||||
|
- activity cards;
|
||||||
|
- search providers.
|
||||||
|
|
||||||
|
## 4. Vault
|
||||||
|
|
||||||
|
Vault остается пользовательским рабочим пространством. Он должен быть максимально понятным снаружи.
|
||||||
|
|
||||||
|
Пример:
|
||||||
|
|
||||||
|
```text
|
||||||
|
VerstakVault/
|
||||||
|
.verstak/
|
||||||
|
db.sqlite
|
||||||
|
config.json
|
||||||
|
plugins/
|
||||||
|
plugin-state/
|
||||||
|
cache/
|
||||||
|
trash/
|
||||||
|
Clients/
|
||||||
|
Romashka/
|
||||||
|
Notes/
|
||||||
|
Overview.md
|
||||||
|
Files/
|
||||||
|
Screenshots/
|
||||||
|
Projects/
|
||||||
|
```
|
||||||
|
|
||||||
|
Правила:
|
||||||
|
|
||||||
|
- пользовательские документы не прячутся в непрозрачные blob-таблицы без необходимости;
|
||||||
|
- SQLite хранит индексы, связи, историю, состояние UI, plugin metadata;
|
||||||
|
- файловая структура должна оставаться пригодной для ручного восстановления;
|
||||||
|
- имена заметок и файлов остаются человекочитаемыми;
|
||||||
|
- sync не является единственным способом доступа к данным.
|
||||||
|
|
||||||
|
## 5. Plugin Runtime
|
||||||
|
|
||||||
|
Плагины загружаются динамически из каталогов. Официальные плагины используют тот же механизм, что и сторонние.
|
||||||
|
|
||||||
|
Папки плагинов:
|
||||||
|
|
||||||
|
```text
|
||||||
|
VerstakVault/.verstak/plugins/
|
||||||
|
official.files/
|
||||||
|
official.notes/
|
||||||
|
official.markdown-editor/
|
||||||
|
|
||||||
|
~/.config/verstak/plugins/
|
||||||
|
user.local-plugin/
|
||||||
|
```
|
||||||
|
|
||||||
|
Порядок загрузки:
|
||||||
|
|
||||||
|
1. Найти plugin manifests.
|
||||||
|
2. Проверить schemaVersion и apiVersion.
|
||||||
|
3. Проверить enabled/disabled state.
|
||||||
|
4. Проверить обязательные capabilities.
|
||||||
|
5. Запросить permissions.
|
||||||
|
6. Запустить backend sidecar, если нужен.
|
||||||
|
7. Загрузить frontend bundle, если нужен.
|
||||||
|
8. Принять регистрации capabilities и contributions.
|
||||||
|
9. Перевести плагин в состояние loaded/degraded/failed/incompatible.
|
||||||
|
|
||||||
|
## 6. Backend Model
|
||||||
|
|
||||||
|
Не использовать Go `plugin` как основной механизм. Он плохо подходит для кроссплатформенного desktop-приложения из-за ABI, версий компилятора и сборки под разные ОС.
|
||||||
|
|
||||||
|
Предпочтительная модель:
|
||||||
|
|
||||||
|
- плагин может быть pure frontend;
|
||||||
|
- плагин может быть pure manifest/data;
|
||||||
|
- плагин может иметь backend sidecar;
|
||||||
|
- sidecar общается с core через локальный RPC;
|
||||||
|
- core выдает sidecar только разрешенные API;
|
||||||
|
- прямой произвольный доступ к vault и OS запрещен по умолчанию.
|
||||||
|
|
||||||
|
Sidecar может быть написан на Go, Rust, Python или другом языке, если он соблюдает протокол.
|
||||||
|
|
||||||
|
## 7. Frontend Model
|
||||||
|
|
||||||
|
Плагин поставляет frontend bundle:
|
||||||
|
|
||||||
|
```text
|
||||||
|
frontend/
|
||||||
|
index.js
|
||||||
|
style.css
|
||||||
|
```
|
||||||
|
|
||||||
|
Frontend bundle не должен напрямую обращаться к Wails backend methods как к глобальному хаосу. Он работает через `VerstakPluginAPI`, который предоставляет:
|
||||||
|
|
||||||
|
- registerView;
|
||||||
|
- registerSettingsPanel;
|
||||||
|
- registerCommand;
|
||||||
|
- registerFileAction;
|
||||||
|
- callBackend;
|
||||||
|
- readSettings/writeSettings;
|
||||||
|
- subscribe/publish events;
|
||||||
|
- requestCapability.
|
||||||
|
|
||||||
|
## 8. Capability Registry
|
||||||
|
|
||||||
|
Плагины связываются не по имени друг друга, а через capabilities.
|
||||||
|
|
||||||
|
Пример:
|
||||||
|
|
||||||
|
```text
|
||||||
|
editor.text
|
||||||
|
editor.text.markdown
|
||||||
|
viewer.file
|
||||||
|
viewer.image
|
||||||
|
preview.markdown
|
||||||
|
workspace.files
|
||||||
|
workspace.notes
|
||||||
|
capture.browser
|
||||||
|
activity.provider
|
||||||
|
secret-store
|
||||||
|
search.provider
|
||||||
|
```
|
||||||
|
|
||||||
|
Файловый плагин не зависит от `official.markdown-editor`. Он проверяет, есть ли capability `editor.text.markdown`. Если есть - показывает действие "Редактировать". Если нет - действие не появляется.
|
||||||
|
|
||||||
|
## 9. Plugin Manager UI
|
||||||
|
|
||||||
|
Core обязан иметь окно управления плагинами с первого платформенного этапа.
|
||||||
|
|
||||||
|
Функции:
|
||||||
|
|
||||||
|
- список установленных плагинов;
|
||||||
|
- enable/disable;
|
||||||
|
- status: loaded, disabled, failed, incompatible, degraded;
|
||||||
|
- version и apiVersion;
|
||||||
|
- source: official, local, third-party;
|
||||||
|
- capabilities provided;
|
||||||
|
- required/optional capabilities;
|
||||||
|
- permissions;
|
||||||
|
- кнопка "Settings", если плагин предоставляет settings panels;
|
||||||
|
- diagnostics/error log.
|
||||||
|
|
||||||
|
Выключение плагина не удаляет пользовательские данные.
|
||||||
|
|
||||||
|
## 10. Settings Registry
|
||||||
|
|
||||||
|
Настройки плагинов не должны быть произвольными экранами, спрятанными в разных местах.
|
||||||
|
|
||||||
|
Плагин регистрирует settings panels:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"contributes": {
|
||||||
|
"settingsPanels": [
|
||||||
|
{
|
||||||
|
"id": "official.notes.general",
|
||||||
|
"title": "Notes",
|
||||||
|
"component": "settings.general"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Core показывает кнопку настроек у выбранного плагина и открывает соответствующую панель/окно.
|
||||||
|
|
||||||
|
## 11. Event Bus
|
||||||
|
|
||||||
|
Event bus связывает плагины без прямых импортов.
|
||||||
|
|
||||||
|
Примеры событий:
|
||||||
|
|
||||||
|
- `vault.opened`;
|
||||||
|
- `case.selected`;
|
||||||
|
- `file.added`;
|
||||||
|
- `file.changed`;
|
||||||
|
- `note.saved`;
|
||||||
|
- `activity.recorded`;
|
||||||
|
- `browser.capture.received`;
|
||||||
|
- `plugin.enabled`;
|
||||||
|
- `plugin.disabled`.
|
||||||
|
|
||||||
|
События должны иметь стабильные схемы. Плагин не должен полагаться на приватные поля другого плагина.
|
||||||
|
|
||||||
|
## 12. Sync Boundary
|
||||||
|
|
||||||
|
Sync server и browser extension выносятся в отдельные репозитории, но должны использовать общие protocol contracts.
|
||||||
|
|
||||||
|
Sync не должен знать о внутренних UI-плагинах. Он синхронизирует:
|
||||||
|
|
||||||
|
- vault metadata;
|
||||||
|
- files/blobs;
|
||||||
|
- plugin state where allowed;
|
||||||
|
- plugin data через зарегистрированные storage namespaces.
|
||||||
|
|
||||||
|
Плагины должны явно указывать, какие данные можно синхронизировать, а какие локальны только на устройстве.
|
||||||
|
|
||||||
|
|
@ -0,0 +1,173 @@
|
||||||
|
# Verstak Repositories
|
||||||
|
|
||||||
|
## 1. Организация
|
||||||
|
|
||||||
|
Для GitHub/Gitea лучше использовать organization `verstak` или аналогичную общую группу. Внутри нее живут отдельные репозитории одной продуктовой идеи.
|
||||||
|
|
||||||
|
Project board можно вести на уровне organization: roadmap, issues, milestones, cross-repo tasks.
|
||||||
|
|
||||||
|
## 2. Минимальный набор репозиториев
|
||||||
|
|
||||||
|
### `verstak-desktop`
|
||||||
|
|
||||||
|
Основное desktop-приложение.
|
||||||
|
|
||||||
|
Содержит:
|
||||||
|
|
||||||
|
- Core Platform;
|
||||||
|
- UI Shell;
|
||||||
|
- plugin loader;
|
||||||
|
- capability registry;
|
||||||
|
- settings window;
|
||||||
|
- plugin manager UI;
|
||||||
|
- vault API;
|
||||||
|
- storage API;
|
||||||
|
- event bus;
|
||||||
|
- sync client boundary;
|
||||||
|
- dev harness для локальных плагинов.
|
||||||
|
|
||||||
|
Не содержит:
|
||||||
|
|
||||||
|
- notes как обязательный модуль;
|
||||||
|
- file manager как обязательный модуль;
|
||||||
|
- markdown editor как обязательный модуль;
|
||||||
|
- browser extension код;
|
||||||
|
- sync server код.
|
||||||
|
|
||||||
|
### `verstak-official-plugins`
|
||||||
|
|
||||||
|
Монорепозиторий официальных плагинов.
|
||||||
|
|
||||||
|
Содержит:
|
||||||
|
|
||||||
|
```text
|
||||||
|
plugins/
|
||||||
|
files/
|
||||||
|
notes/
|
||||||
|
markdown-editor/
|
||||||
|
markdown-preview/
|
||||||
|
file-preview/
|
||||||
|
activity/
|
||||||
|
journal/
|
||||||
|
browser-inbox/
|
||||||
|
search/
|
||||||
|
secrets/
|
||||||
|
templates/
|
||||||
|
packages/
|
||||||
|
plugin-sdk/
|
||||||
|
shared-ui/
|
||||||
|
test-harness/
|
||||||
|
```
|
||||||
|
|
||||||
|
Официальные плагины должны устанавливаться и загружаться так же, как сторонние. Нельзя делать для них скрытый privileged path, кроме явно описанных platform permissions.
|
||||||
|
|
||||||
|
### `verstak-sdk`
|
||||||
|
|
||||||
|
Общие контракты для разработки плагинов.
|
||||||
|
|
||||||
|
Содержит:
|
||||||
|
|
||||||
|
- manifest schema;
|
||||||
|
- TypeScript SDK;
|
||||||
|
- RPC protocol definitions;
|
||||||
|
- capability contracts;
|
||||||
|
- event schemas;
|
||||||
|
- test helpers;
|
||||||
|
- plugin packaging tools;
|
||||||
|
- examples.
|
||||||
|
|
||||||
|
На раннем этапе SDK может жить в `verstak-official-plugins/packages/plugin-sdk`, но должен быть выделен в отдельный репозиторий, когда API начнет стабилизироваться.
|
||||||
|
|
||||||
|
### `verstak-sync-server`
|
||||||
|
|
||||||
|
Отдельный сервер синхронизации.
|
||||||
|
|
||||||
|
Содержит:
|
||||||
|
|
||||||
|
- HTTP API;
|
||||||
|
- auth/pairing;
|
||||||
|
- device registry;
|
||||||
|
- vault operation log;
|
||||||
|
- blob upload/download;
|
||||||
|
- conflict handling;
|
||||||
|
- retention/deleted file policy;
|
||||||
|
- server migrations;
|
||||||
|
- deployment docs.
|
||||||
|
|
||||||
|
Sync server не должен импортировать desktop UI или official plugins.
|
||||||
|
|
||||||
|
### `verstak-browser-extension`
|
||||||
|
|
||||||
|
Расширение браузера.
|
||||||
|
|
||||||
|
Содержит:
|
||||||
|
|
||||||
|
- Firefox/Chromium extension;
|
||||||
|
- local pairing with Verstak;
|
||||||
|
- page capture;
|
||||||
|
- selected text capture;
|
||||||
|
- link sending;
|
||||||
|
- pending queue if desktop is offline;
|
||||||
|
- domain bindings support;
|
||||||
|
- protocol docs for browser inbox plugin.
|
||||||
|
|
||||||
|
Расширение не должно напрямую знать внутреннюю структуру notes/files/activity. Оно отправляет события в local receiver, а обработка идет через плагин `official.browser-inbox`.
|
||||||
|
|
||||||
|
## 3. Репозитории позже
|
||||||
|
|
||||||
|
### `verstak-plugin-registry`
|
||||||
|
|
||||||
|
Каталог доступных плагинов:
|
||||||
|
|
||||||
|
- official plugin index;
|
||||||
|
- third-party plugin metadata;
|
||||||
|
- signatures/checksums;
|
||||||
|
- compatibility matrix;
|
||||||
|
- install URLs.
|
||||||
|
|
||||||
|
Не нужен в первый этап, если плагины ставятся вручную из локальной папки или из `verstak-official-plugins`.
|
||||||
|
|
||||||
|
### `verstak-docs`
|
||||||
|
|
||||||
|
Публичная документация:
|
||||||
|
|
||||||
|
- user guide;
|
||||||
|
- developer guide;
|
||||||
|
- plugin authoring guide;
|
||||||
|
- sync setup;
|
||||||
|
- security model;
|
||||||
|
- migration guides.
|
||||||
|
|
||||||
|
Может быть отдельным репозиторием позже. Сейчас допустимо держать архитектурные документы рядом с `verstak-desktop`.
|
||||||
|
|
||||||
|
## 4. Что не дробить слишком рано
|
||||||
|
|
||||||
|
Не стоит сразу создавать отдельный репозиторий на каждый официальный плагин. Это увеличит накладные расходы и усложнит синхронные изменения SDK/API.
|
||||||
|
|
||||||
|
Лучше:
|
||||||
|
|
||||||
|
```text
|
||||||
|
verstak-official-plugins - один repo для официальных плагинов
|
||||||
|
```
|
||||||
|
|
||||||
|
А отдельные repo оставить для сторонних плагинов или крупных независимых модулей.
|
||||||
|
|
||||||
|
## 5. Версионирование
|
||||||
|
|
||||||
|
Версии должны существовать на трех уровнях:
|
||||||
|
|
||||||
|
- app version: версия `verstak-desktop`;
|
||||||
|
- platform apiVersion: версия API плагинов;
|
||||||
|
- plugin version: версия конкретного плагина.
|
||||||
|
|
||||||
|
Плагин объявляет:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"version": "0.1.0",
|
||||||
|
"apiVersion": "1"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Core может загрузить плагин только при совместимости `apiVersion`.
|
||||||
|
|
||||||
|
|
@ -0,0 +1,309 @@
|
||||||
|
# Verstak Plugin System
|
||||||
|
|
||||||
|
## 1. Цель
|
||||||
|
|
||||||
|
Плагины превращают Верстак из монолитного приложения в платформу. Любая пользовательская функция должна быть реализуема как плагин:
|
||||||
|
|
||||||
|
- заметки;
|
||||||
|
- файловый менеджер;
|
||||||
|
- редактор;
|
||||||
|
- просмотрщик;
|
||||||
|
- журнал;
|
||||||
|
- активность;
|
||||||
|
- браузерный inbox;
|
||||||
|
- поиск;
|
||||||
|
- секреты;
|
||||||
|
- импорт;
|
||||||
|
- шаблоны дел.
|
||||||
|
|
||||||
|
## 2. Структура плагина
|
||||||
|
|
||||||
|
```text
|
||||||
|
official.notes/
|
||||||
|
plugin.json
|
||||||
|
frontend/
|
||||||
|
index.js
|
||||||
|
style.css
|
||||||
|
backend/
|
||||||
|
plugin-linux-amd64
|
||||||
|
plugin-windows-amd64.exe
|
||||||
|
migrations/
|
||||||
|
001_init.sql
|
||||||
|
assets/
|
||||||
|
README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
Не каждый плагин обязан иметь frontend/backend/migrations. Manifest обязателен.
|
||||||
|
|
||||||
|
## 3. Manifest
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"id": "official.notes",
|
||||||
|
"name": "Notes",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"apiVersion": "1",
|
||||||
|
"description": "Markdown notes inside Verstak cases.",
|
||||||
|
"source": "official",
|
||||||
|
"provides": [
|
||||||
|
"workspace.notes",
|
||||||
|
"entity.note"
|
||||||
|
],
|
||||||
|
"requires": [
|
||||||
|
"vault.files"
|
||||||
|
],
|
||||||
|
"optionalRequires": [
|
||||||
|
"editor.text.markdown",
|
||||||
|
"preview.markdown",
|
||||||
|
"search.provider"
|
||||||
|
],
|
||||||
|
"permissions": [
|
||||||
|
"vault.read",
|
||||||
|
"vault.write",
|
||||||
|
"storage.namespace",
|
||||||
|
"ui.register",
|
||||||
|
"events.publish",
|
||||||
|
"events.subscribe"
|
||||||
|
],
|
||||||
|
"frontend": {
|
||||||
|
"entry": "frontend/index.js",
|
||||||
|
"style": "frontend/style.css"
|
||||||
|
},
|
||||||
|
"backend": {
|
||||||
|
"type": "sidecar",
|
||||||
|
"entry": {
|
||||||
|
"linux-amd64": "backend/plugin-linux-amd64",
|
||||||
|
"windows-amd64": "backend/plugin-windows-amd64.exe"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"contributes": {
|
||||||
|
"views": [],
|
||||||
|
"commands": [],
|
||||||
|
"settingsPanels": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4. Capabilities Instead Of Plugin Names
|
||||||
|
|
||||||
|
Плагины не должны требовать конкретный плагин, если им нужна способность.
|
||||||
|
|
||||||
|
Плохо:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"requires": ["official.markdown-editor"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Хорошо:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"optionalRequires": ["editor.text.markdown"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Так можно заменить редактор, поставить два редактора или временно выключить предпросмотр без поломки файлового плагина.
|
||||||
|
|
||||||
|
## 5. Required And Optional Capabilities
|
||||||
|
|
||||||
|
`requires` - без этих capabilities плагин не может работать.
|
||||||
|
|
||||||
|
`optionalRequires` - без них плагин работает в degraded mode.
|
||||||
|
|
||||||
|
Пример:
|
||||||
|
|
||||||
|
```text
|
||||||
|
official.notes
|
||||||
|
requires:
|
||||||
|
vault.files
|
||||||
|
optionalRequires:
|
||||||
|
editor.text.markdown
|
||||||
|
preview.markdown
|
||||||
|
search.provider
|
||||||
|
```
|
||||||
|
|
||||||
|
Если нет `preview.markdown`, заметки работают, но кнопка предпросмотра не появляется.
|
||||||
|
|
||||||
|
## 6. Plugin States
|
||||||
|
|
||||||
|
Core должен различать состояния:
|
||||||
|
|
||||||
|
- `discovered` - manifest найден;
|
||||||
|
- `disabled` - пользователь выключил;
|
||||||
|
- `loading` - идет загрузка;
|
||||||
|
- `loaded` - успешно загружен;
|
||||||
|
- `degraded` - работает без optional capabilities;
|
||||||
|
- `failed` - ошибка загрузки/запуска;
|
||||||
|
- `incompatible` - неподдерживаемый apiVersion/schemaVersion;
|
||||||
|
- `missing-required-capability` - не хватает обязательной capability.
|
||||||
|
|
||||||
|
Состояние видно в Plugin Manager UI.
|
||||||
|
|
||||||
|
## 7. Lifecycle
|
||||||
|
|
||||||
|
```text
|
||||||
|
discover
|
||||||
|
validate manifest
|
||||||
|
check compatibility
|
||||||
|
check enabled state
|
||||||
|
resolve required capabilities
|
||||||
|
request permissions
|
||||||
|
run migrations
|
||||||
|
start backend sidecar
|
||||||
|
load frontend bundle
|
||||||
|
register capabilities
|
||||||
|
register contributions
|
||||||
|
activate
|
||||||
|
deactivate
|
||||||
|
shutdown
|
||||||
|
```
|
||||||
|
|
||||||
|
Lifecycle hooks:
|
||||||
|
|
||||||
|
- `onInstall`;
|
||||||
|
- `onEnable`;
|
||||||
|
- `onVaultOpen`;
|
||||||
|
- `onActivate`;
|
||||||
|
- `onDeactivate`;
|
||||||
|
- `onDisable`;
|
||||||
|
- `onUninstall`;
|
||||||
|
- `onShutdown`.
|
||||||
|
|
||||||
|
## 8. Contribution Points
|
||||||
|
|
||||||
|
Плагин может регистрировать:
|
||||||
|
|
||||||
|
- sidebar item;
|
||||||
|
- main view;
|
||||||
|
- case tab;
|
||||||
|
- file action;
|
||||||
|
- note action;
|
||||||
|
- context menu item;
|
||||||
|
- command palette command;
|
||||||
|
- settings panel;
|
||||||
|
- search provider;
|
||||||
|
- activity provider;
|
||||||
|
- importer;
|
||||||
|
- exporter;
|
||||||
|
- vault scanner;
|
||||||
|
- protocol receiver.
|
||||||
|
|
||||||
|
Contribution должен быть декларативным, где возможно. Runtime callbacks нужны только для поведения.
|
||||||
|
|
||||||
|
## 9. Plugin Settings
|
||||||
|
|
||||||
|
Окно настроек плагинов - обязательная часть core.
|
||||||
|
|
||||||
|
Плагин объявляет settings panels:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"contributes": {
|
||||||
|
"settingsPanels": [
|
||||||
|
{
|
||||||
|
"id": "official.markdown-editor.general",
|
||||||
|
"title": "Markdown Editor",
|
||||||
|
"component": "settings.general"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Plugin Manager показывает кнопку настроек только если у плагина есть settings panels.
|
||||||
|
|
||||||
|
Настройки хранятся в namespace плагина:
|
||||||
|
|
||||||
|
```text
|
||||||
|
plugin_settings.official.markdown-editor
|
||||||
|
```
|
||||||
|
|
||||||
|
Плагин не должен читать/писать настройки другого плагина без разрешения.
|
||||||
|
|
||||||
|
## 10. Enable/Disable Rules
|
||||||
|
|
||||||
|
Выключение плагина:
|
||||||
|
|
||||||
|
- убирает его UI contributions;
|
||||||
|
- убирает commands/actions;
|
||||||
|
- отзывает provided capabilities;
|
||||||
|
- останавливает sidecar;
|
||||||
|
- сохраняет данные плагина;
|
||||||
|
- не удаляет пользовательские файлы;
|
||||||
|
- публикует событие `plugin.disabled`.
|
||||||
|
|
||||||
|
Включение плагина:
|
||||||
|
|
||||||
|
- повторно проверяет совместимость;
|
||||||
|
- выполняет pending migrations;
|
||||||
|
- регистрирует contributions;
|
||||||
|
- публикует событие `plugin.enabled`.
|
||||||
|
|
||||||
|
Если другой плагин использовал optional capability выключенного плагина, он переходит в degraded mode. Если required capability исчезла, зависимый плагин должен быть деактивирован или переведен в failed/missing-required state.
|
||||||
|
|
||||||
|
## 11. Permissions
|
||||||
|
|
||||||
|
Минимальный набор permissions:
|
||||||
|
|
||||||
|
```text
|
||||||
|
vault.read
|
||||||
|
vault.write
|
||||||
|
vault.watch
|
||||||
|
storage.namespace
|
||||||
|
storage.migrations
|
||||||
|
events.publish
|
||||||
|
events.subscribe
|
||||||
|
ui.register
|
||||||
|
commands.register
|
||||||
|
network.local
|
||||||
|
network.remote
|
||||||
|
process.spawn
|
||||||
|
secrets.read
|
||||||
|
secrets.write
|
||||||
|
sync.participate
|
||||||
|
```
|
||||||
|
|
||||||
|
Опасные разрешения должны быть видны пользователю до включения плагина:
|
||||||
|
|
||||||
|
- `network.remote`;
|
||||||
|
- `process.spawn`;
|
||||||
|
- `secrets.read`;
|
||||||
|
- `vault.write`;
|
||||||
|
- `sync.participate`.
|
||||||
|
|
||||||
|
## 12. Data Ownership
|
||||||
|
|
||||||
|
Каждый плагин имеет namespace:
|
||||||
|
|
||||||
|
```text
|
||||||
|
plugin_data/<plugin_id>/
|
||||||
|
plugin_settings/<plugin_id>/
|
||||||
|
plugin_cache/<plugin_id>/
|
||||||
|
```
|
||||||
|
|
||||||
|
Пользовательские данные должны отделяться от cache.
|
||||||
|
|
||||||
|
Uninstall не должен автоматически удалять пользовательские данные без явного подтверждения.
|
||||||
|
|
||||||
|
## 13. Packaging
|
||||||
|
|
||||||
|
Плагин распространяется как zip/tar package:
|
||||||
|
|
||||||
|
```text
|
||||||
|
official.notes-0.1.0.vpkg
|
||||||
|
```
|
||||||
|
|
||||||
|
Пакет содержит:
|
||||||
|
|
||||||
|
- `plugin.json`;
|
||||||
|
- frontend bundle;
|
||||||
|
- backend binaries if any;
|
||||||
|
- migrations;
|
||||||
|
- README;
|
||||||
|
- checksums/signature later.
|
||||||
|
|
||||||
|
На первом этапе допустима ручная установка папкой в plugin directory.
|
||||||
|
|
||||||
|
|
@ -0,0 +1,303 @@
|
||||||
|
# Official Plugins
|
||||||
|
|
||||||
|
Официальные плагины - это базовый набор инструментов Верстака. Они не должны быть скрытыми частями core. Их задача - показать, что платформа действительно работает через capabilities и contribution points.
|
||||||
|
|
||||||
|
## 1. `official.files`
|
||||||
|
|
||||||
|
Назначение:
|
||||||
|
|
||||||
|
- дерево/список файлов внутри дела;
|
||||||
|
- добавление файлов;
|
||||||
|
- перемещение/копирование в vault;
|
||||||
|
- открытие системным приложением;
|
||||||
|
- file metadata;
|
||||||
|
- file actions registry consumer.
|
||||||
|
|
||||||
|
Provides:
|
||||||
|
|
||||||
|
```text
|
||||||
|
workspace.files
|
||||||
|
vault.files
|
||||||
|
entity.file
|
||||||
|
file.browser
|
||||||
|
```
|
||||||
|
|
||||||
|
Optional requires:
|
||||||
|
|
||||||
|
```text
|
||||||
|
editor.text
|
||||||
|
viewer.file
|
||||||
|
preview.file
|
||||||
|
search.provider
|
||||||
|
```
|
||||||
|
|
||||||
|
Поведение:
|
||||||
|
|
||||||
|
- если есть подходящий editor capability, показывает "Edit";
|
||||||
|
- если есть viewer/preview capability, показывает "Preview";
|
||||||
|
- если нет, оставляет "Open externally".
|
||||||
|
|
||||||
|
## 2. `official.notes`
|
||||||
|
|
||||||
|
Назначение:
|
||||||
|
|
||||||
|
- markdown notes as first-class Verstak entities;
|
||||||
|
- canonical `Notes/` folder inside case/project;
|
||||||
|
- Overview note;
|
||||||
|
- note metadata;
|
||||||
|
- note links.
|
||||||
|
|
||||||
|
Provides:
|
||||||
|
|
||||||
|
```text
|
||||||
|
workspace.notes
|
||||||
|
entity.note
|
||||||
|
note.registry
|
||||||
|
```
|
||||||
|
|
||||||
|
Requires:
|
||||||
|
|
||||||
|
```text
|
||||||
|
vault.files
|
||||||
|
```
|
||||||
|
|
||||||
|
Optional requires:
|
||||||
|
|
||||||
|
```text
|
||||||
|
editor.text.markdown
|
||||||
|
preview.markdown
|
||||||
|
search.provider
|
||||||
|
```
|
||||||
|
|
||||||
|
Важное правило:
|
||||||
|
|
||||||
|
- title и filename должны оставаться синхронизированными;
|
||||||
|
- filename - человекочитаемая проекция title;
|
||||||
|
- при конфликте имени не добавлять `_2` молча, а показывать понятный conflict dialog.
|
||||||
|
|
||||||
|
## 3. `official.markdown-editor`
|
||||||
|
|
||||||
|
Назначение:
|
||||||
|
|
||||||
|
- редактирование markdown/text;
|
||||||
|
- toolbar;
|
||||||
|
- save flow;
|
||||||
|
- dirty state;
|
||||||
|
- keyboard shortcuts.
|
||||||
|
|
||||||
|
Provides:
|
||||||
|
|
||||||
|
```text
|
||||||
|
editor.text
|
||||||
|
editor.text.markdown
|
||||||
|
editor.note.markdown
|
||||||
|
```
|
||||||
|
|
||||||
|
Optional requires:
|
||||||
|
|
||||||
|
```text
|
||||||
|
preview.markdown
|
||||||
|
```
|
||||||
|
|
||||||
|
Не должен:
|
||||||
|
|
||||||
|
- сам решать, где хранятся notes;
|
||||||
|
- напрямую зависеть от `official.notes`;
|
||||||
|
- тащить file manager внутрь себя.
|
||||||
|
|
||||||
|
## 4. `official.markdown-preview`
|
||||||
|
|
||||||
|
Назначение:
|
||||||
|
|
||||||
|
- безопасный markdown render;
|
||||||
|
- internal `verstak://` links;
|
||||||
|
- optional syntax highlight.
|
||||||
|
|
||||||
|
Provides:
|
||||||
|
|
||||||
|
```text
|
||||||
|
preview.markdown
|
||||||
|
viewer.markdown
|
||||||
|
```
|
||||||
|
|
||||||
|
Optional requires:
|
||||||
|
|
||||||
|
```text
|
||||||
|
link.resolver
|
||||||
|
```
|
||||||
|
|
||||||
|
## 5. `official.file-preview`
|
||||||
|
|
||||||
|
Назначение:
|
||||||
|
|
||||||
|
- просмотр изображений;
|
||||||
|
- просмотр text-like файлов;
|
||||||
|
- базовый PDF/image metadata preview, если возможно;
|
||||||
|
- fallback to system open.
|
||||||
|
|
||||||
|
Provides:
|
||||||
|
|
||||||
|
```text
|
||||||
|
viewer.file
|
||||||
|
viewer.image
|
||||||
|
viewer.text
|
||||||
|
preview.file
|
||||||
|
```
|
||||||
|
|
||||||
|
## 6. `official.activity`
|
||||||
|
|
||||||
|
Назначение:
|
||||||
|
|
||||||
|
- сбор activity events;
|
||||||
|
- отображение истории;
|
||||||
|
- реконструкция работы;
|
||||||
|
- подсказки для worklog.
|
||||||
|
|
||||||
|
Provides:
|
||||||
|
|
||||||
|
```text
|
||||||
|
activity.log
|
||||||
|
activity.provider
|
||||||
|
activity.reconstruction
|
||||||
|
```
|
||||||
|
|
||||||
|
Subscribes:
|
||||||
|
|
||||||
|
```text
|
||||||
|
file.opened
|
||||||
|
file.changed
|
||||||
|
note.saved
|
||||||
|
action.started
|
||||||
|
browser.capture.received
|
||||||
|
case.selected
|
||||||
|
```
|
||||||
|
|
||||||
|
## 7. `official.journal`
|
||||||
|
|
||||||
|
Назначение:
|
||||||
|
|
||||||
|
- ручной журнал работ;
|
||||||
|
- billable/non-billable;
|
||||||
|
- отчеты по делу/клиенту;
|
||||||
|
- принятие suggested time из activity.
|
||||||
|
|
||||||
|
Provides:
|
||||||
|
|
||||||
|
```text
|
||||||
|
worklog
|
||||||
|
journal
|
||||||
|
report.worklog
|
||||||
|
```
|
||||||
|
|
||||||
|
Optional requires:
|
||||||
|
|
||||||
|
```text
|
||||||
|
activity.reconstruction
|
||||||
|
```
|
||||||
|
|
||||||
|
## 8. `official.browser-inbox`
|
||||||
|
|
||||||
|
Назначение:
|
||||||
|
|
||||||
|
- прием ссылок, выделенного текста, страниц и snippets из browser extension;
|
||||||
|
- pending queue;
|
||||||
|
- привязка доменов к делам;
|
||||||
|
- создание inbox entries;
|
||||||
|
- превращение inbox entry в note/link/file/activity.
|
||||||
|
|
||||||
|
Provides:
|
||||||
|
|
||||||
|
```text
|
||||||
|
capture.browser
|
||||||
|
browser.inbox
|
||||||
|
domain.binding
|
||||||
|
```
|
||||||
|
|
||||||
|
Requires:
|
||||||
|
|
||||||
|
```text
|
||||||
|
network.local
|
||||||
|
```
|
||||||
|
|
||||||
|
Optional requires:
|
||||||
|
|
||||||
|
```text
|
||||||
|
workspace.notes
|
||||||
|
activity.log
|
||||||
|
search.provider
|
||||||
|
```
|
||||||
|
|
||||||
|
## 9. `official.search`
|
||||||
|
|
||||||
|
Назначение:
|
||||||
|
|
||||||
|
- общий поиск по vault;
|
||||||
|
- индекс notes/files/activity/worklog;
|
||||||
|
- providers from plugins;
|
||||||
|
- typo/layout tolerant search later.
|
||||||
|
|
||||||
|
Provides:
|
||||||
|
|
||||||
|
```text
|
||||||
|
search
|
||||||
|
search.provider
|
||||||
|
search.indexer
|
||||||
|
```
|
||||||
|
|
||||||
|
## 10. `official.secrets`
|
||||||
|
|
||||||
|
Назначение:
|
||||||
|
|
||||||
|
- защищенное хранилище клиентских доступов;
|
||||||
|
- SSH/CMS/VPS/database/API secrets;
|
||||||
|
- bridge secret, sync token, device private key, pairing token;
|
||||||
|
- permissions for secret access.
|
||||||
|
|
||||||
|
Provides:
|
||||||
|
|
||||||
|
```text
|
||||||
|
secret-store
|
||||||
|
secrets.read-ui
|
||||||
|
secrets.write-ui
|
||||||
|
```
|
||||||
|
|
||||||
|
Важное правило:
|
||||||
|
|
||||||
|
- секреты не должны храниться как обычный markdown/plain text;
|
||||||
|
- доступ к secret-store должен идти через permissions;
|
||||||
|
- плагины не получают `secrets.read` автоматически.
|
||||||
|
|
||||||
|
## 11. `official.templates`
|
||||||
|
|
||||||
|
Назначение:
|
||||||
|
|
||||||
|
- шаблоны дел;
|
||||||
|
- client/project/server/device structures;
|
||||||
|
- initial folder/note/action layout.
|
||||||
|
|
||||||
|
Provides:
|
||||||
|
|
||||||
|
```text
|
||||||
|
case.templates
|
||||||
|
```
|
||||||
|
|
||||||
|
Optional requires:
|
||||||
|
|
||||||
|
```text
|
||||||
|
workspace.notes
|
||||||
|
workspace.files
|
||||||
|
```
|
||||||
|
|
||||||
|
## 12. Первый минимальный набор
|
||||||
|
|
||||||
|
Для первого платформенного этапа достаточно:
|
||||||
|
|
||||||
|
- `official.files`;
|
||||||
|
- `official.notes`;
|
||||||
|
- `official.markdown-editor`;
|
||||||
|
- `official.markdown-preview`;
|
||||||
|
- `official.activity`;
|
||||||
|
- `official.browser-inbox`;
|
||||||
|
|
||||||
|
Но все они должны быть настоящими динамическими плагинами, даже если поставляются вместе с приложением.
|
||||||
|
|
||||||
|
|
@ -0,0 +1,128 @@
|
||||||
|
# Migration Strategy
|
||||||
|
|
||||||
|
## 1. Цель миграции
|
||||||
|
|
||||||
|
Нужно перейти от текущего приложения к платформе, не потеряв исходный смысл Верстака:
|
||||||
|
|
||||||
|
- local-first vault;
|
||||||
|
- дела как центр контекста;
|
||||||
|
- человекочитаемые файлы;
|
||||||
|
- заметки, файлы, журнал, активность, браузерные материалы вокруг дела;
|
||||||
|
- синхронизация и расширение как отдельные части, а не ядро смысла.
|
||||||
|
|
||||||
|
Миграция не должна быть "просто разнести App.svelte". Это смена архитектурной модели.
|
||||||
|
|
||||||
|
## 2. Нельзя делать
|
||||||
|
|
||||||
|
- Нельзя добавлять новые функции в монолитный `App.svelte`.
|
||||||
|
- Нельзя делать official plugins скрытыми compile-time modules.
|
||||||
|
- Нельзя связывать плагины по именам, если нужна capability.
|
||||||
|
- Нельзя делать notes/files/editor обязательными частями core.
|
||||||
|
- Нельзя ломать существующий vault layout без миграционного плана.
|
||||||
|
- Нельзя хранить секреты как обычные заметки или plain text.
|
||||||
|
- Нельзя молча менять title/filename note при конфликте.
|
||||||
|
|
||||||
|
## 3. Этап 1 - Platform Skeleton
|
||||||
|
|
||||||
|
Сделать в `verstak-desktop`:
|
||||||
|
|
||||||
|
- plugin manifest schema;
|
||||||
|
- plugin discovery from plugin directories;
|
||||||
|
- enable/disable state;
|
||||||
|
- plugin manager UI;
|
||||||
|
- plugin status model;
|
||||||
|
- capability registry;
|
||||||
|
- contribution registry;
|
||||||
|
- settings registry;
|
||||||
|
- basic event bus;
|
||||||
|
- diagnostics panel.
|
||||||
|
|
||||||
|
Проверки:
|
||||||
|
|
||||||
|
- приложение запускается без плагинов;
|
||||||
|
- приложение показывает пустой Plugin Manager;
|
||||||
|
- тестовый плагин появляется в списке;
|
||||||
|
- enable/disable работает;
|
||||||
|
- failed plugin не роняет приложение.
|
||||||
|
|
||||||
|
## 4. Этап 2 - Frontend Plugin Host
|
||||||
|
|
||||||
|
Сделать:
|
||||||
|
|
||||||
|
- загрузку frontend bundle;
|
||||||
|
- `VerstakPluginAPI`;
|
||||||
|
- registration of views/settings/commands;
|
||||||
|
- plugin UI error boundary;
|
||||||
|
- settings panel invocation from Plugin Manager.
|
||||||
|
|
||||||
|
Проверки:
|
||||||
|
|
||||||
|
- тестовый плагин регистрирует view;
|
||||||
|
- тестовый плагин регистрирует settings panel;
|
||||||
|
- выключение плагина убирает view/settings;
|
||||||
|
- ошибка в plugin UI не роняет shell.
|
||||||
|
|
||||||
|
## 5. Этап 3 - Backend Sidecar Host
|
||||||
|
|
||||||
|
Сделать:
|
||||||
|
|
||||||
|
- sidecar launch protocol;
|
||||||
|
- local RPC;
|
||||||
|
- permission-scoped API;
|
||||||
|
- sidecar shutdown/restart;
|
||||||
|
- logs/diagnostics.
|
||||||
|
|
||||||
|
Проверки:
|
||||||
|
|
||||||
|
- sidecar отвечает health check;
|
||||||
|
- sidecar не получает API без permissions;
|
||||||
|
- падение sidecar переводит плагин в failed;
|
||||||
|
- disable останавливает sidecar.
|
||||||
|
|
||||||
|
## 6. Этап 4 - Official Plugin Extraction
|
||||||
|
|
||||||
|
Выносить функции по одной:
|
||||||
|
|
||||||
|
1. `official.markdown-preview`;
|
||||||
|
2. `official.markdown-editor`;
|
||||||
|
3. `official.files`;
|
||||||
|
4. `official.notes`;
|
||||||
|
5. `official.activity`;
|
||||||
|
6. `official.browser-inbox`.
|
||||||
|
|
||||||
|
После каждого выноса:
|
||||||
|
|
||||||
|
- проверить build;
|
||||||
|
- проверить запуск;
|
||||||
|
- проверить Plugin Manager;
|
||||||
|
- проверить enable/disable;
|
||||||
|
- проверить degraded mode при отключении optional plugin;
|
||||||
|
- проверить, что старые данные vault открываются;
|
||||||
|
- проверить, что UI contributions исчезают при disable.
|
||||||
|
|
||||||
|
## 7. Этап 5 - Repository Split
|
||||||
|
|
||||||
|
Когда plugin runtime работает:
|
||||||
|
|
||||||
|
- оставить core и shell в `verstak-desktop`;
|
||||||
|
- вынести official plugins в `verstak-official-plugins`;
|
||||||
|
- вынести sync server в `verstak-sync-server`;
|
||||||
|
- вынести browser extension в `verstak-browser-extension`;
|
||||||
|
- выделить `verstak-sdk` после стабилизации API.
|
||||||
|
|
||||||
|
Не начинать с физического split repo, пока runtime не умеет грузить плагины локально.
|
||||||
|
|
||||||
|
## 8. Definition Of Done
|
||||||
|
|
||||||
|
Платформенный переход можно считать состоявшимся, когда:
|
||||||
|
|
||||||
|
- core запускается без official plugins;
|
||||||
|
- official plugins лежат вне core modules;
|
||||||
|
- notes/files/editor/preview/activity работают как плагины;
|
||||||
|
- Plugin Manager умеет включать/выключать плагины;
|
||||||
|
- плагин может иметь свое settings окно;
|
||||||
|
- capability registry управляет видимостью actions;
|
||||||
|
- отсутствие optional capability не считается ошибкой;
|
||||||
|
- existing vault открывается без миграционной потери данных;
|
||||||
|
- документация соответствует реализации.
|
||||||
|
|
||||||
|
|
@ -0,0 +1,121 @@
|
||||||
|
# AGENTS.md - Verstak Platform
|
||||||
|
|
||||||
|
Руководство для coding agents, работающих над Верстаком.
|
||||||
|
|
||||||
|
Язык общения с пользователем: русский. Названия API, файлов, команд, commit messages и технических сущностей можно оставлять на английском.
|
||||||
|
|
||||||
|
## 1. Назначение проекта
|
||||||
|
|
||||||
|
Верстак - local-first рабочая платформа вокруг дел. Дело собирает заметки, файлы, документы, ссылки, действия, журнал, активность, браузерные материалы и секреты в одном локальном vault.
|
||||||
|
|
||||||
|
Новая архитектурная цель: Верстак не монолитное приложение, а платформа с динамическими плагинами.
|
||||||
|
|
||||||
|
## 2. Главные инварианты
|
||||||
|
|
||||||
|
- Core не содержит notes/files/editor/activity/journal/browser inbox как обязательные внутренние фичи.
|
||||||
|
- Пользовательские функции реализуются как динамические плагины.
|
||||||
|
- Официальные плагины работают через тот же plugin runtime, что и сторонние.
|
||||||
|
- Плагины зависят от capabilities, а не от конкретных plugin IDs, если им нужна способность.
|
||||||
|
- Отсутствие optional capability не ошибка; UI action просто не появляется или плагин работает в degraded mode.
|
||||||
|
- Выключение плагина не удаляет пользовательские данные.
|
||||||
|
- Vault остается local-first и человекочитаемым.
|
||||||
|
- Sync server, browser extension и official plugins должны быть выделяемыми репозиториями.
|
||||||
|
- Секреты не хранятся как plain text notes.
|
||||||
|
|
||||||
|
## 3. Архитектурные документы
|
||||||
|
|
||||||
|
Перед работой прочитать:
|
||||||
|
|
||||||
|
- `verstak-platform-docs/01_Product_Vision.md`
|
||||||
|
- `verstak-platform-docs/02_Platform_Architecture.md`
|
||||||
|
- `verstak-platform-docs/04_Plugin_System.md`
|
||||||
|
- `verstak-platform-docs/05_Official_Plugins.md`
|
||||||
|
- `verstak-platform-docs/06_Migration_Strategy.md`
|
||||||
|
|
||||||
|
Если код противоречит документам, не молча подгонять документы под код. Сначала понять, это старый монолитный долг или осознанное новое решение.
|
||||||
|
|
||||||
|
## 4. Plugin Rules
|
||||||
|
|
||||||
|
Manifest обязателен. Плагин должен объявлять:
|
||||||
|
|
||||||
|
- `id`;
|
||||||
|
- `name`;
|
||||||
|
- `version`;
|
||||||
|
- `apiVersion`;
|
||||||
|
- `provides`;
|
||||||
|
- `requires`;
|
||||||
|
- `optionalRequires`;
|
||||||
|
- `permissions`;
|
||||||
|
- `frontend/backend` entry, если есть;
|
||||||
|
- `contributes`, если есть UI/actions/settings.
|
||||||
|
|
||||||
|
Нельзя:
|
||||||
|
|
||||||
|
- импортировать другой плагин напрямую;
|
||||||
|
- вызывать приватные backend methods другого плагина;
|
||||||
|
- читать чужой storage namespace без разрешения;
|
||||||
|
- создавать actions, если нет нужной capability;
|
||||||
|
- ронять приложение при ошибке плагина.
|
||||||
|
|
||||||
|
## 5. Plugin Manager
|
||||||
|
|
||||||
|
Plugin Manager UI - обязательный core-модуль.
|
||||||
|
|
||||||
|
Он должен показывать:
|
||||||
|
|
||||||
|
- installed plugins;
|
||||||
|
- enable/disable;
|
||||||
|
- status: loaded, disabled, failed, incompatible, degraded;
|
||||||
|
- version/apiVersion;
|
||||||
|
- source: official/local/third-party;
|
||||||
|
- provided capabilities;
|
||||||
|
- required/optional capabilities;
|
||||||
|
- permissions;
|
||||||
|
- settings button, если плагин предоставляет settings panel;
|
||||||
|
- diagnostics/error text.
|
||||||
|
|
||||||
|
## 6. Note/File Rules
|
||||||
|
|
||||||
|
Для notes:
|
||||||
|
|
||||||
|
- canonical folder: `Notes/`;
|
||||||
|
- Overview note: `Notes/Overview.md`;
|
||||||
|
- title и filename должны быть синхронизированы;
|
||||||
|
- filename строится из title как человекочитаемая безопасная проекция;
|
||||||
|
- при конфликте имени операция не должна молча добавлять `_2`; нужен conflict dialog/suggestion.
|
||||||
|
|
||||||
|
Для files:
|
||||||
|
|
||||||
|
- file plugin не должен жестко зависеть от markdown editor;
|
||||||
|
- edit/preview actions появляются только при наличии соответствующих capabilities;
|
||||||
|
- opening external app остается fallback.
|
||||||
|
|
||||||
|
## 7. Work Style
|
||||||
|
|
||||||
|
После каждого этапа:
|
||||||
|
|
||||||
|
- build/check;
|
||||||
|
- targeted tests;
|
||||||
|
- ручная проверка ключевого сценария, если есть UI;
|
||||||
|
- self-review на забытые imports, dead code, orphaned functions, old monolith paths;
|
||||||
|
- обновить документацию, если изменился контракт.
|
||||||
|
|
||||||
|
Не принимать отчет "сделано", пока не проверено:
|
||||||
|
|
||||||
|
- приложение собирается;
|
||||||
|
- старые сценарии не сломаны;
|
||||||
|
- plugin enable/disable не оставляет мусорный UI;
|
||||||
|
- optional capabilities реально optional;
|
||||||
|
- failed plugin не роняет shell.
|
||||||
|
|
||||||
|
## 8. Запрет на монолитный откат
|
||||||
|
|
||||||
|
Если задача просит добавить новую пользовательскую функцию, сначала определить:
|
||||||
|
|
||||||
|
- это core platform feature?
|
||||||
|
- это official plugin?
|
||||||
|
- это capability?
|
||||||
|
- это contribution point?
|
||||||
|
|
||||||
|
Если функция относится к заметкам, файлам, редакторам, просмотру, activity, journal, browser inbox, search, secrets, import/export - по умолчанию это плагин, а не core.
|
||||||
|
|
||||||
Loading…
Reference in New Issue