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