# Публикация и обновления

> Как поделиться карточкой через GitHub, с каких адресов её можно установить, как установка привязывается к коммиту, как обновления доходят до пользователей и когда они спрашивают снова, и версии карточки и протокола.

Source: https://docs.neurosquad.ai/ru/card-sdk/publishing

Магазина нет: **карточка опубликована, когда она на GitHub**, и ставится по своему адресу на GitHub.
Проверка — по желанию: чтобы карточка попала в [каталог проверенных](https://docs.neurosquad.ai/ru/card-sdk/verified-cards) приложения
(поиск прямо из меню добавления и значок «Проверена»), пришлите pull request в
`glmn-ai/neurosquad-cards`, как описано в его [SUBMITTING.md](https://github.com/glmn-ai/neurosquad-cards/blob/HEAD/docs/SUBMITTING.md). Каждая проверенная версия
закреплена на одном коммите.

## Опубликовать

1. Выполните `npx @neurosquad/card-sdk validate` и `pack --dry-run`. Исправьте все ошибки; прочитайте
превью диалога установки глазами незнакомого человека.
2. Закоммитьте всё, что нужно карточке, — включая результат сборки (`dist/`): приложение никогда
ничего не собирает. `pack` перечисляет ровно то, что будет установлено.
3. Запушьте в публичный репозиторий на GitHub (приватные тоже работают — для пользователей, которые
добавят GitHub-токен).
4. При желании поставьте тег релиза: `git tag v1.0.0 && git push --tags` — и создайте из тега релиз
на GitHub.
5. Сообщите людям адрес.

**Несколько карточек в одном репозитории** — это нормально: каждая лежит в своей папке со своим
манифестом и ставится как `owner/repo/path/to/folder`.

## С каких адресов можно установить

| Адрес | Что ставится | За чем следят обновления |
| --- | --- | --- |
| `owner/repo` | свежий коммит ветки по умолчанию | ветка по умолчанию |
| `owner/repo@main` | эта ветка | эта ветка |
| `owner/repo@v1.2.0` | этот тег | ни за чем — тег неизменен |
| `owner/repo@<40-hex commit>` | этот коммит | ни за чем |
| `https://github.com/owner/repo/releases/tag/v1.2.0` | этот релиз | **последний релиз** |
| `owner/repo/cards/pomodoro`, `https://github.com/owner/repo/tree/main/cards/pomodoro` | карточка из этой папки | как выше |

Подойдут и `github.com/owner/repo`, `https://github.com/owner/repo.git`. Ссылку (ref), в которой
есть `/`, нужно указывать через `@ref`.

**Привязка к коммиту.** Какой бы ни был адрес, приложение сводит его к одному коммиту и ставит файлы
этого коммита. Коммит, заданный хешем, должен быть достижим из ветки по умолчанию репозитория —
коммит, который есть только в форке, отклоняется, — а переименованный или переданный репозиторий
нужно ставить под его текущим именем. Приложение записывает коммит и хеш дерева всех файлов.
Введённый пользователем адрес — не идентичность карточки, ею является `github:owner/repo[/folder]`,
— поэтому обновление сохраняет разрешения карточки, её хранилище и все копии на всех холстах.

## Как обновления доходят до пользователей

- Приложение проверяет через минуту после запуска, потом каждые 24 часа и когда пользователь
нажимает **Check for updates**.
- Более новый коммит скачивается и проверяется, а потом предлагается: **Update** в настройках и точка
на карточке. **Ничего не применяется автоматически.**
- Пользователь видит, что меняется: новую версию, старый → новый коммит со ссылкой на сравнение в
GitHub и разницу в разрешениях:
  - **новые разрешения** и **новые сетевые хосты** → обновление ждёт согласия пользователя;
  - **разрешения, которые больше не нужны** → отзываются при обновлении;
  - новые **необязательные** разрешения → показываются как «может попросить позже» и никогда не
выдаются сами;
  - новые или переформулированные **инструменты**, новые порты или порты с другим типом, новые
**секретные настройки**, изменённые **displayName, автор или домашняя страница** → обновление
тоже ждёт согласия пользователя.
- При обновлении каждая открытая копия карточки перезагружается с `launch === 'updated'`.
Хранилище и настройки переносятся — если вы поменяли их структуру, переносите данные в коде.
- Если в новом приложении манифест перестал проходить проверку, карточка показывается сломанной, с
причиной; запускать её всё равно не будут.

> Перезапись тега или истории не протащит код мимо пользователей: тот же коммит, скачанный заново с
> другим содержимым, отклоняется, а каждое обновление показывается до применения. Но с каждым
> принятым обновлением пользователи доверяют вам — защитите свой аккаунт GitHub (2FA) и проверяйте
> пул-реквесты в вашу карточку как код, который будет работать на чужих машинах.

## Версии

**`version` вашей карточки** — для информации (установка привязана к коммитам), но пользователи
видят её в диалоге установки, в диалоге обновления и в **Settings → Custom cards**. Пользуйтесь
SemVer и повышайте её в каждом релизе. Ломающие изменения портов и инструментов описывайте в
описании: от них могут зависеть чужие карточки и привычки агентов.

**`minAppVersion`** не даёт поставить карточку в слишком старое приложение.

**Протокол** версионируется отдельно: `"protocol": 1` в манифесте, `CARD_PROTOCOL_VERSION` в SDK.

- Новые методы, события и необязательные поля появляются **внутри** протокола 1. Проверяйте их
наличие через `card.host.supports('method.name')` и продолжайте работать без них.
- Ломающее изменение стало бы протоколом 2. Приложение, которое знает только 1, отклонит карточку под
2 с сообщением «нужен более новый NeuroSquad»; карточки протокола 1 приложение продолжало бы
обслуживать параллельно ещё минимум год.
- Обновлять `@neurosquad/card-sdk` в пределах одной мажорной версии безопасно; пересоберите и
опубликуйте заново.

## Изменение разрешений и того, что предлагает карточка

Добавив обязательное разрешение или сетевой хост — или инструмент, порт, секретную настройку, или
поменяв имя, автора или домашнюю страницу карточки, — вы заставляете каждого текущего пользователя
принять обновление, прежде чем он получит из него **хоть что-то**, включая исправления ошибок.
Подумайте о том, чтобы:

- сделать новое разрешение **необязательным** и просить его, когда пользователь дойдёт до функции;
- выпустить изменение разрешений отдельным релизом и объяснить его в описании.

## Как вывести карточку из обращения

Не удаляйте репозиторий: установленным копиям он для работы не нужен, но нужен для обновлений и
переустановки. Напишите об этом в описании и укажите замену.
