Correct the install notes against a real install

The notes described a machine that no longer matches: the runtime paths
they hardcoded do not exist on this one, and three of their claims turned
out to be wrong when the plugin was actually installed.

What was wrong, and what is true:

1. Runtime paths. `~/.dsh/dsh-runtimes/...` is only where a downloaded
   runtime lives; this install carries it in the application. The notes
   now probe both locations and take the one that exists.

2. "You cannot install into the desktop profile from the CLI". The
   launcher refuses `desktop` only for booting and for --dump-config;
   `dsh plugin --profile desktop ...` is allowed because the Desktop
   carrier passes manageDesktopProfile. Verified: install, list, remove
   all work, and each one keeps dsh.profile.bundles in sync by itself.

3. "An application restart is required". Not on Desktop. The base bundle
   enables hmr whenever profileContext is supplied, and the application
   supplies it, so editing the profile manifest recomposes the tree live
   and the client half reaches an open page over the HMR transport. The
   application had started at 16:36 and the pill appeared in that same
   process after the 16:41 install.

Also documented, because it decides whether an edit reaches the harness:
`file:` on Windows produces hardlinks out of the pnpm store, so an
in-place write is visible immediately but an atomic replace silently
breaks the link; `link:` is a junction and always sees edits. The plugin
is now installed as `link:` for that reason.

The design note keeps its original text and carries dated corrections
plus a table of what was actually verified, so the next install does not
repeat the probing.
This commit is contained in:
Антонов Антон Владимирович
2026-10-28 16:51:26 +03:00
parent 63f7a4b301
commit 89cde16ddc
2 changed files with 97 additions and 23 deletions
@@ -197,14 +197,16 @@ Cannot assign to read only property 'url' of object '#<_Response>'
**Зависимостей от других плагинов нет.**
**Установка.** Менеджер плагинов принимает локальный путь как спецификацию (`inspect` читает `package.json` по абсолютному пути; GitHub-проверка для путей пропускается). Установка идёт через страницу плагинов в приложении: профиль рабочего стола управляется приложением, из CLI в него ставить нельзя. Ставится долгой командой референс-плагина, форма та же.
**Установка.** Менеджер плагинов принимает локальный путь как спецификацию (`inspect` читает `package.json` по абсолютному пути; GitHub-проверка для путей пропускается). Ставить можно и со страницы плагинов в приложении, и из CLI: `dsh plugin --profile desktop add <pkg>` в десктопной поставке разрешён (запуск и `--dump-config` по этому профилю закрыты, управление пакетами — нет). Ровно эта команда и была использована.
*Поправка после установки (2026-10-28).* Здесь стояло «из CLI в него ставить нельзя» — неверно: launcher отбивает `desktop` только в режиме запуска, а `plugin` пропускает, если приложение передало `manageDesktopProfile`.
Два требования, которые надо соблюсти, иначе установка откажется:
- пакет должен объявить совместимость с рантаймом (`peerDependencies` на DSH) — версия рабочего рантайма **0.2.0-rc.2**;
- пакет должен объявить совместимость с рантаймом (`peerDependencies` на DSH) — версия рабочего рантайма при установке была **0.2.1-rc.3**, и пакет прошёл проверку без исключений в `compatibility.json`;
- пакет должен объявлять бандл (`dsh.bundle.patch`), иначе установка сообщит `not-a-bundle`.
**Про перезапуск.** Плагины собираются при старте хоста. Если HMR в профиле не включён, уже запущенная композиция остаётся до перезапуска — перезагрузки страницы недостаточно. В `cordis.yml` рабочего профиля HMR не упомянут, поэтому исходить надо из того, что **потребуется перезапуск приложения**, а он прервёт текущий разговор. Порядок такой: сначала собрать и проверить пакет, перезапуск — последним шагом.
**Про перезапуск.** *Поправка после установки (2026-10-28).* Здесь стояло «потребуется перезапуск приложения» — на десктопе не потребовался. Базовый бандл включает `hmr` при живом `profileContext` (а приложение его передаёт), `dsh-hmr` следит за манифестом профиля, и правка `dsh.profile.bundles` пересобирает дерево на ходу; клиентская половина доезжает до открытой страницы по HMR-транспорту. Проверено: приложение стартовало в 16:36, пакет встал в 16:41, ячейка появилась в том же процессе. Перезапуск нужен только там, где HMR погашен (бандлы `headless`, `sdk`, `acp`) или профиль правили в обход пересборки; перезагрузки страницы в этом случае действительно недостаточно.
## Что остаётся сборщику
@@ -218,7 +220,7 @@ Cannot assign to read only property 'url' of object '#<_Response>'
## Как проверять
**Готовые инструменты** (лежат в `.recon/`, запускаются встроенным Node из `C:\Users\Anton\.dsh\dsh-runtimes\dsh-primary-runtime\dependencies\node\bin\node.exe`):
**Готовые инструменты** (лежат в `.recon/`, запускаются встроенным Node из `C:\Users\Anton\.dsh\dsh-runtimes\dsh-primary-runtime\dependencies\node\bin\node.exe`; на машине, где ставился плагин, такого пути нет — рантайм вложен в приложение, см. `INSTALL.md`):
| Файл | Что делает |
|---|---|
@@ -244,6 +246,24 @@ Cannot assign to read only property 'url' of object '#<_Response>'
## Решённое
**Установка:** владелец выбрал ставить плагин в рабочий харнесс. Потребуется запись за пределами рабочей песочницы (в `~/.dsh/profiles/desktop`) и перезапуск приложения.
**Установка:** владелец выбрал ставить плагин в рабочий харнесс. Запись идёт в `~/.dsh/profiles/desktop`; перезапуск приложения, как выяснилось при установке, не требуется — HMR на десктопе включён (см. поправку выше).
**Git:** владелец выбрал завести локальный репозиторий. Заведён в `C:\Users\Anton\Documents\src\costs-plugin`, дизайн и спайки закоммичены.
**Git:** владелец выбрал завести локальный репозиторий. Заведён в `C:\Users\Anton\Documents\src\costs-plugin`, дизайн и спайки закоммичены; позже перенесён на `git.trtd.pro/antonov/dsh-cost-plugin`.
## Как это встало на самом деле (2026-10-28)
Записано, чтобы следующая установка не повторяла проверок заново.
| Что проверяли | Итог |
|---|---|
| `dsh plugin --profile desktop add file:<tgz>` | работает; сам дописывает бандл в `dsh.profile.bundles` |
| `dsh plugin --profile desktop remove …` | работает; сам убирает запись из списка бандлов |
| `dsh --profile desktop --dump-config` | отказ: `profile "desktop" is managed exclusively by the Electron application` |
| голая `pnpm add --dir …` | ставит пакет, но список бандлов не трогает — шаг со списком обязателен |
| `file:` на Windows | pnpm делает **хардлинки** из store: правка на месте видна, атомарная замена файла рвёт линк |
| `link:` на Windows | junction на исходник: правки видны всегда; pnpm предупреждает про `peerDependencies` (у нас `react`), для браузерной половины это неважно |
| перезапуск приложения | не потребовался: `hmr` включён через `profileContext`, ячейка появилась в работающем процессе |
| тумблер в Plugins | доступен: host-строка `plugin-manager` включается тем же `profileContext` |
| `plugin-manager`/`tool-plugin-manager` в `dsh-base` | `plugin-manager` — `!!js "!ctx.get('profileContext')"`, `tool-plugin-manager` — всегда `disabled: true` |
Открытым осталось расхождение валюты: хост кладёт в ответ `currency: 'RUB'`, а клиент печатает `\u20BD` жёстко и `currency` не читает. Пока провайдер один, это незаметно; при втором — цифра будет подписана неверно.