@iwonz/ywtc 4.1.0 → 4.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,48 +4,24 @@
4
4
 
5
5
  # ywtc
6
6
 
7
- ## Описание
8
-
9
- `ywtc` — CLI для переноса страниц между Yandex Wiki и Confluence и экспорта в Markdown или автономный HTML. Утилита сохраняет структуру, ссылки и вложения, явно отмечает деградации и продолжает прерванные операции по state-файлу. Исходные данные и страницы назначения автоматически не удаляются.
7
+ `ywtc` — CLI для переноса страниц между Yandex Wiki и Confluence и экспорта в Markdown или автономный HTML. Он сохраняет иерархию и доступное содержимое, проверяет результат, продолжает прерванные операции и ничего не удаляет автоматически.
10
8
 
11
9
  Требуются Node.js `>=24` и npm `>=11.5.1`. Лицензия — [MIT](LICENSE).
12
10
 
13
- ## Возможности
14
-
15
- | Исходный материал | Как переносится |
16
- | --- | --- |
17
- | Страницы и структура | Одна страница, полное структурное поддерево или граф связанных страниц. Иерархия восстанавливается, циклы обрабатываются без повторного переноса. Пустая страница-раздел переносится как корректная пустая страница, а не как fallback. |
18
- | Текст и оформление | Заголовки, абзацы, жирное/курсивное/зачёркнутое и цветное начертание, списки и задачи, цитаты, разделители, inline/preformatted code с языком и обычные таблицы преобразуются в нативную или семантически эквивалентную разметку destination. |
19
- | Секции и колонки | YFM `layout/block` и Confluence page layouts сохраняются нативными секциями и колонками в Yandex Wiki и Confluence. HTML использует адаптивную сетку; Markdown сохраняет все ячейки по порядку и отмечает линеаризацию как adaptation без ухудшения статуса. |
20
- | Ссылки и якоря | Ссылки между выбранными страницами переписываются на destination, якоря сохраняются. Внешние ссылки и ссылки за пределы выбранного набора остаются исходными. |
21
- | Вложения | Переносятся все доступные через API для скачивания файлы, включая PNG/JPEG/GIF/WebP/SVG, PDF, ZIP, DOC/DOCX, XLS/XLSX и PPT/PPTX. Файлы передаются потоково, совпадения имён разрешаются стабильно, размер и SHA-256 проверяются. |
22
- | Изображения | Прикреплённые изображения становятся attachments destination или локальными файлами экспорта. Внешние изображения остаются внешними; подписи и размеры сохраняются, если destination это поддерживает. |
23
- | Специальная разметка | В обе стороны сопоставляются notes ↔ `info`/`tip`/`warning`/`note`, cuts ↔ `expand`, tree ↔ `children`, задачи, code, anchors, page/attachment links и изображения. Tabs становятся статическими секциями, Grid — проверяемой статической таблицей. Такие полные эквивалентные представления считаются adaptation и остаются `complete`. Безопасный Storage Format и YFM сохраняются нативно при переносе внутри одного провайдера. |
24
- | Комментарии | По умолчанию все доступные комментарии страницы собираются в один архивный комментарий: отдельные раскрываемые ветки сохраняют участников, авторов, даты, статусы, inline-контекст, удалённые записи и вложенность ответов. Вложения, на которые есть ссылки в тексте комментариев, складываются в один проверяемый ZIP с hash-prefixed именами и manifest. Для Markdown/HTML создаются локальные секции и ZIP. |
25
- | Конструкции без точного эквивалента | Создаётся читаемый fallback и при необходимости raw snapshot. Если весь payload представлен и проверен, это adaptation со статусом `complete`; только потеря данных, значимой структуры или невозможность проверки дают degradation и `partial`. |
26
-
27
- ### Не переносится
28
-
29
- | Ограничение | Поведение ywtc |
30
- | --- | --- |
31
- | История версий | Переносится только актуальное содержимое страницы. |
32
- | Реакции на комментарии | Не копируются и не влияют на список участников архива. |
33
- | Комментарии непосредственно к attachments, blog posts и custom content | Не входят в архив страницы; читаются только footer/inline page comments. |
34
- | Пользовательские сущности, watchers, права и ограничения доступа | Не создаются; исходное авторство комментариев сохраняется в архивном тексте, а destination-объекты создаются пользователем текущего токена и наследуют права destination. |
35
- | Удалённые, недоступные или не возвращённые source API страницы | Не восстанавливаются; недоступность и пропуски фиксируются в state и отчёте. |
36
- | Точная пиксельная геометрия, произвольный CSS и активные скрипты | Не исполняются и не обещают визуальную идентичность. Содержимое и поддерживаемая структура сохраняются нативно или статически; неподдерживаемая часть получает читаемый fallback и raw snapshot. |
37
- | Сторонние и неизвестные macros/виджеты | Не подменяются приблизительным macro без доказанного эквивалента: сохраняются безопасным статическим представлением и raw snapshot с явной degradation. |
38
- | Внешние файлы и изображения, не принадлежащие source | Не копируются; абсолютный URL, подпись и доступные размеры сохраняются как external reference без ухудшения статуса. Недоступный source-managed ресурс считается неполным переносом. |
39
- | Активные скрипты, iframe, формы и интерактивное поведение embed-объектов | Не исполняются в destination; вместо них сохраняется безопасное статическое представление или raw snapshot. |
40
- | Пиксельная идентичность и поведение vendor-specific элементов без эквивалента | Используется ближайшее семантическое представление; различия явно отмечаются в отчёте. |
41
-
42
- ## Установка
11
+ ## Быстрый старт
43
12
 
44
13
  ```bash
45
- # npm
46
14
  npm install -g @iwonz/ywtc
15
+ ywtc init --interactive
16
+ ywtc migrate --interactive
17
+ ```
47
18
 
48
- # npx без глобальной установки
19
+ Первый мастер создаёт рабочий каталог, настраивает Yandex Wiki и Confluence и проверяет соединения. Второй собирает параметры переноса и по умолчанию выполняет dry-run; live-запуск начинается только после подтверждения.
20
+
21
+ Другие способы запуска:
22
+
23
+ ```bash
24
+ # Без глобальной установки
49
25
  npx @iwonz/ywtc@latest --version
50
26
 
51
27
  # Homebrew
@@ -54,261 +30,230 @@ brew trust --tap iwonz/ywtc
54
30
  brew install ywtc
55
31
  ```
56
32
 
57
- Homebrew 7 требует доверить сторонний tap; команда `brew trust` относится только к `iwonz/ywtc`.
33
+ Обновление: `ywtc update` проверяет версию, `ywtc update --install` обновляет через обнаруженный канал, `--via npm|brew` выбирает канал явно.
58
34
 
59
- Обновление:
35
+ ## Возможности
60
36
 
61
- ```bash
62
- ywtc update # только проверка
63
- ywtc update --install # канал текущей установки
64
- ywtc update --install --via brew # явно через Homebrew
65
- ```
37
+ | Материал | Результат |
38
+ | --- | --- |
39
+ | Страницы и структура | `page`, полное `subtree` или рекурсивный граф `linked`. Иерархия восстанавливается, циклы не создают повторов, пустая страница-раздел остаётся корректной пустой страницей. |
40
+ | Текст и таблицы | Сохраняются заголовки, начертания и цвет, списки и задачи, цитаты, разделители, inline/preformatted code с языком и обычные таблицы. Destination получает нативную или семантически эквивалентную разметку. |
41
+ | Секции и колонки | YFM `layout/block` и Confluence layouts преобразуются в нативные секции и колонки. HTML использует адаптивную сетку; Markdown сохраняет содержимое ячеек в исходном порядке. |
42
+ | Ссылки и якоря | Ссылки внутри выбранного набора переписываются на destination; якоря сохраняются. Внешние ссылки и переходы за границу набора остаются исходными. |
43
+ | Файлы и изображения | Доступные через API вложения передаются потоково с проверкой размера и SHA-256. Поддерживаются любые скачиваемые файлы, включая PNG/JPEG/GIF/WebP/SVG, PDF, ZIP, DOCX, XLSX и PPTX. Коллизии имён разрешаются стабильно. |
44
+ | Специальная разметка | Notes ↔ callout macros, cuts ↔ expand, tree ↔ children, задачи, code, anchors, page/attachment links и изображения получают ближайший эквивалент. Tabs становятся секциями, Grid — проверяемой статической таблицей. |
45
+ | Комментарии | По умолчанию footer/inline page comments архивируются с авторами, датами, статусами и иерархией ответов. Явно упомянутые вложения собираются в проверяемый ZIP с hash-prefixed именами и manifest. |
46
+ | Надёжность содержимого | Новая страница сразу создаётся с полным source-derived body, а не placeholder. Ошибка отдельного ресурса не блокирует текст: остаётся source-ссылка и повторяемый outcome. После записи destination перечитывается и проверяется. |
47
+ | Различия платформ | Безопасная normalization и полная adaptation считаются `complete`. Если эквивалента нет, ywtc сохраняет читаемый fallback и при необходимости raw snapshot; недоказанная полнота становится degradation. |
48
+
49
+ ### Ограничения
50
+
51
+ | Не переносится как исходная сущность | Что сохраняется |
52
+ | --- | --- |
53
+ | История версий | Текущее содержимое; последующие обновления destination образуют его обычную историю версий. |
54
+ | Реакции; комментарии к attachments, blog posts и custom content | Только footer/inline comments страницы. |
55
+ | Пользователи, watchers, права и ограничения доступа | Авторство комментариев остаётся в архивном тексте; новые объекты создаёт владелец токена и они наследуют права destination. |
56
+ | Недоступные или не возвращённые API страницы | Причина и незавершённая ветка фиксируются в state и отчёте. |
57
+ | Произвольный CSS, scripts и неизвестные интерактивные widgets/macros | Безопасное статическое представление, fallback или raw snapshot; тихой потери быть не должно. |
58
+ | Внешние файлы и изображения | Исходный абсолютный URL, alt и доступные размеры; внешние данные не скачиваются. Недоступный source-managed ресурс считается неполным переносом. |
66
59
 
67
- ## Минимальный сценарий
60
+ ## Совместимость
68
61
 
69
- - [ ] Установите `ywtc` одним из способов выше.
70
- - [ ] Выполните `ywtc init --interactive`.
71
- - [ ] Выполните `ywtc migrate --interactive`.
62
+ | Source | Destination |
63
+ | --- | --- |
64
+ | Yandex Wiki | Confluence, Yandex Wiki, Markdown, HTML |
65
+ | Confluence | Yandex Wiki, Confluence, Markdown, HTML |
66
+
67
+ | Система | Поддерживаемый контракт | Авторизация |
68
+ | --- | --- | --- |
69
+ | Yandex Wiki | Public API v1; новые необязательные поля допускаются | OAuth или пользовательский IAM; `X-Org-Id`/`X-Cloud-Org-Id` |
70
+ | Confluence Data Center | 7.9+ без искусственной верхней границы | Bearer PAT |
71
+ | Confluence Cloud | REST v2 для страниц, REST v1 для attachments | Email + API token |
72
+
73
+ Confluence Server, Data Center Basic Auth и OAuth app-flow не поддерживаются. Перед чтением страниц и записью `doctor`/`migrate` проверяет готовность REST API: startup/maintenance HTML и неполный JSON останавливают операцию без создания state или destination-объектов. После восстановления Confluence повторите команду; если сервер исправен, проверьте `baseUrl` и `deployment`. Контрактные тесты не заменяют live-сертификацию каждой patch-версии.
72
74
 
73
75
  ## Конфигурация
74
76
 
75
- Для рабочих команд каталог выбирается в порядке: `--workdir` → текущий каталог, если непосредственно в нём есть `ywtc.config.yaml` → `~/.ywtc`. Поиск по родительским каталогам не выполняется. `ywtc init --interactive` предлагает путь с default `~/.ywtc`; переданный `--workdir` становится редактируемым начальным значением. `migrate` автоматически инициализирует отсутствующий workspace.
77
+ Рабочий каталог выбирается в порядке `--workdir` → `ywtc.config.yaml` непосредственно в текущем каталоге → `~/.ywtc`. Родительские каталоги не просматриваются.
76
78
 
77
79
  ```text
78
80
  ~/.ywtc/
79
- ├── ywtc.config.yaml # подключения, настройки и токены; mode 0600 при создании
80
- └── .states/ # state, cache и отчёты
81
+ ├── ywtc.config.yaml # подключения, настройки и токены
82
+ └── .states/ # state, cache, backups и отчёты
81
83
  ```
82
84
 
83
- `ywtc init --interactive` требует TTY, проводит через обязательные настройки обоих провайдеров, скрывает токены и делает только read-only connection probes. Проверка подтверждает API и авторизацию, но не права конкретных страниц: они проверяются `doctor` или `migrate`. Для существующего workspace доступны изменение выбранных профилей, выход без изменений и настройка с нуля с backup прежнего YAML в `.states/backups/`; state не удаляется.
84
-
85
- `ywtc migrate --interactive` использует тот же порядок выбора workspace, последовательно настраивает source, destination, scope, комментарии и файловый ZIP, а затем по умолчанию запускает dry-run. После него можно открыть отчёт, изменить параметры, повторить проверку или явно начать live-перенос. При неполном inventory, root error, `failed`, `blocked` или настоящем `conflict` live-действие скрывается.
86
-
87
- Обычный `ywtc init` без wizard создаёт безопасный пустой шаблон для автоматизации или ручного управления. Полный пример с Yandex Wiki, Confluence Data Center, Confluence Cloud и сетевыми лимитами: [`ywtc.config.example.yaml`](ywtc.config.example.yaml).
85
+ `ywtc init --interactive` настраивает и проверяет оба провайдера; `ywtc init` создаёт пустой шаблон для автоматизации. `migrate` создаёт отсутствующий workspace, но до API-запросов требует заполнить обязательные поля. Проверка мастера подтверждает API и авторизацию, но не права конкретных страниц: их проверяют `doctor` или `migrate`. Конфигурация строгая, неизвестные поля отклоняются; process environment её не переопределяет. Локальный файл игнорируется Git, новый создаётся с mode `0600`, секреты маскируются в выводе. Полный шаблон: [`ywtc.config.example.yaml`](ywtc.config.example.yaml).
88
86
 
89
- ### Поля профилей
87
+ ### Поля `ywtc.config.yaml`
90
88
 
91
- | Поле | Для кого | Обязательность / значения | Назначение |
89
+ | Поле | Профиль | Значения / default | Назначение |
92
90
  | --- | --- | --- | --- |
93
- | `defaults.timeoutMs` | файл | `1000..300000`, default `30000` | Таймаут HTTP-запроса |
94
- | `defaults.concurrency` | файл | `1..64`, default `4` | Общая параллельность операции |
95
- | `connections.<name>` | файл | минимум один; имя `[a-z0-9._-]+` | Именованное подключение |
96
- | `type` | все профили | `yandex-wiki` или `confluence` | Тип провайдера |
97
- | `token` | все профили | непустой для используемого профиля | OAuth, IAM, PAT или API token |
98
- | `apiUrl` | Yandex Wiki | URL Public API v1 | API endpoint |
99
- | `webUrl` | Yandex Wiki | URL | Базовый адрес Wiki для ссылок и выбора профиля |
100
- | `authType` | Yandex Wiki | `oauth` (default) или `iam` | Схема авторизации |
101
- | `organization.type` | Yandex Wiki | `yandex360` (default) или `cloud` | Заголовок `X-Org-Id` или `X-Cloud-Org-Id` |
102
- | `organization.id` | Yandex Wiki | непустая строка | ID организации |
103
- | `deployment` | Confluence | `data-center` или `cloud` | Тип развёртывания |
104
- | `baseUrl` | Confluence | URL | Адрес инстанса, включая context path |
105
- | `authType` | Confluence | `pat` для Data Center; `api-token` для Cloud | Схема авторизации |
106
- | `email` | Confluence Cloud | непустой для используемого профиля | Email Atlassian-аккаунта |
107
- | `limits.readConcurrency` | все профили | `1..64`, default `4` | Параллельные чтения |
108
- | `limits.writeConcurrency` | все профили | `1..32`, default `2` | Параллельные записи |
109
- | `limits.downloadConcurrency` | все профили | `1..32`, default `2` | Параллельные скачивания |
110
- | `limits.uploadConcurrency` | все профили | `1..32`, default `2` | Параллельные загрузки |
111
- | `limits.requestsPerSecond` | все профили | `1..1000`, default `8` | Средняя частота запросов |
112
- | `limits.burst` | все профили | `1..1000`, default `8` | Допустимый кратковременный burst |
113
-
114
- Конфигурация строгая: неизвестные поля считаются ошибкой. Все значения, включая токены, email, таймауты и лимиты, читаются только из `ywtc.config.yaml`; process environment их не переопределяет. Файл рабочего каталога игнорируется Git, а токены маскируются в диагностике и отчётах.
115
-
116
- ## Направления и совместимость
117
-
118
- | Source | Destination | Поддержка |
119
- | --- | --- | --- |
120
- | Yandex Wiki | Confluence | Да |
121
- | Yandex Wiki | Yandex Wiki | Да, включая другой профиль или инстанс |
122
- | Confluence | Yandex Wiki | Да |
123
- | Confluence | Confluence | Да, включая другой профиль или инстанс |
124
- | Yandex Wiki или Confluence | Markdown | Да |
125
- | Yandex Wiki или Confluence | статический HTML | Да |
126
-
127
- | Система | Контракт | Авторизация |
128
- | --- | --- | --- |
129
- | Yandex Wiki | Public API v1; новые необязательные поля принимаются | OAuth или пользовательский IAM; `X-Org-Id`/`X-Cloud-Org-Id` |
130
- | Confluence Data Center | 7.9+ без верхней границы; capabilities проверяются до записи | Bearer PAT |
131
- | Confluence Cloud | REST v2 для страниц и REST v1 для attachments | Email + API token |
132
-
133
- Confluence Server, Data Center Basic Auth и OAuth app-flow не поддерживаются. Совместимость определяется preflight-проверкой необходимых API/capabilities, а не сертификацией каждой patch-версии.
134
-
135
- ## Как получить токены
136
-
137
- ### Yandex Wiki
138
-
139
- - [ ] Создайте приложение в [Яндекс OAuth](https://oauth.yandex.ru/).
140
- - [ ] Выдайте права Wiki на чтение; для destination также нужны права записи.
141
- - [ ] Получите OAuth-токен пользователя с доступом к страницам. Для федеративного пользователя Yandex Cloud допустим IAM-токен и `authType: iam`.
142
- - [ ] Найдите ID организации в **Yandex Tracker → Администрирование → Организации**.
143
- - [ ] Укажите `organization.type: yandex360` для Яндекс 360 или `cloud` для Cloud Organization.
144
- - [ ] Запишите токен в `connections.<name>.token` выбранного профиля.
145
-
146
- ### Confluence Data Center
147
-
148
- - [ ] Откройте **Avatar → Settings → Personal access tokens → Create token**.
149
- - [ ] Создайте PAT и запишите его в `connections.<name>.token`.
150
- - [ ] Используйте `deployment: data-center` и `authType: pat`.
151
- - [ ] Проверьте права на чтение source и создание/изменение страниц и вложений destination.
152
-
153
- ### Confluence Cloud
154
-
155
- - [ ] Создайте [Atlassian API token](https://id.atlassian.com/manage-profile/security/api-tokens).
156
- - [ ] Используйте `deployment: cloud`, `authType: api-token`, `token` и `email`.
157
- - [ ] Запишите API token и email аккаунта непосредственно в выбранный профиль.
158
- - [ ] Проверьте доступ аккаунта к source и destination spaces.
159
-
160
- ## Параметры
91
+ | `defaults.timeoutMs` | общий | `1000..300000`; `30000` | Таймаут HTTP-запроса |
92
+ | `defaults.concurrency` | общий | `1..64`; `4` | Общая параллельность операции |
93
+ | `connections.<name>` | общий | имя `[a-z0-9._-]+` | Именованное подключение |
94
+ | `type` | любой | `yandex-wiki` или `confluence` | Провайдер |
95
+ | `token` | любой | непустой | OAuth, IAM, PAT или API token |
96
+ | `apiUrl` / `webUrl` | Yandex Wiki | URL API v1 / базовый web URL | API-запросы, ссылки и выбор профиля |
97
+ | `authType` | Yandex Wiki | `oauth` или `iam`; `oauth` | Схема авторизации; IAM допустим только с Cloud Organization |
98
+ | `organization.type` | Yandex Wiki | `yandex360` или `cloud`; `yandex360` | Выбирает `X-Org-Id` или `X-Cloud-Org-Id` |
99
+ | `organization.id` | Yandex Wiki | непустой | ID организации |
100
+ | `deployment` | Confluence | `data-center` или `cloud` | Тип инстанса |
101
+ | `baseUrl` | Confluence | URL, включая context path | Базовый адрес API и web |
102
+ | `authType` | Confluence | `pat` или `api-token` | PAT для Data Center; API token для Cloud |
103
+ | `email` | Confluence Cloud | непустой | Atlassian account email для Basic Auth |
104
+ | `limits.readConcurrency` | любой | `1..64`; `4` | Параллельные чтения |
105
+ | `limits.writeConcurrency` | любой | `1..32`; `2` | Параллельные записи |
106
+ | `limits.downloadConcurrency` / `uploadConcurrency` | любой | `1..32`; `2` | Параллельные передачи файлов |
107
+ | `limits.requestsPerSecond` | любой | `1..1000`; `8` | Устойчивая частота запросов |
108
+ | `limits.burst` | любой | `1..1000`; Yandex `8`, Confluence `10` | Кратковременный burst |
109
+
110
+ ### Токены
111
+
112
+ #### Yandex Wiki
113
+
114
+ 1. Создайте приложение в [Яндекс OAuth](https://oauth.yandex.ru/) и выдайте ему [права Wiki](https://yandex.ru/support/wiki/ru/api-ref/access) на чтение, а для destination — на запись.
115
+ 2. Получите OAuth-токен пользователя с доступом к нужным страницам. Для федеративного пользователя Yandex Cloud допустим IAM-токен.
116
+ 3. Найдите ID в **Yandex Tracker → Администрирование → Организации** и выберите `organization.type: yandex360` либо `cloud`.
117
+ 4. Запишите значения в Yandex-профиль; для IAM используйте `authType: iam` и Cloud Organization.
118
+
119
+ #### Confluence Data Center
120
+
121
+ 1. Откройте **Avatar → Settings → Personal access tokens → Create token**; порядок действий описан в [документации Atlassian](https://confluence.atlassian.com/enterprise/using-personal-access-tokens-1026032365.html).
122
+ 2. Запишите PAT в профиль с `deployment: data-center` и `authType: pat`.
123
+ 3. Убедитесь, что пользователь может читать source и создавать страницы и attachments в destination.
124
+
125
+ #### Confluence Cloud
126
+
127
+ 1. Создайте [Atlassian API token](https://id.atlassian.com/manage-profile/security/api-tokens).
128
+ 2. Используйте `deployment: cloud`, `authType: api-token`, `email` и `token`; аккаунту нужен доступ к исходному и целевому spaces.
129
+
130
+ ## CLI
161
131
 
162
132
  ### Команды
163
133
 
164
134
  | Команда | Назначение |
165
135
  | --- | --- |
166
- | `ywtc init [--workdir <path>] [--interactive]` | Создать шаблон либо настроить и проверить подключения в TTY wizard |
167
- | `ywtc doctor [options]` | Проверить workspace; с source и destination выполнить read-only preflight |
168
- | `ywtc migrate --interactive` | Выбрать параметры, выполнить dry-run и явно продолжить live-перенос в TTY wizard |
169
- | `ywtc migrate --source <locator> --destination <locator\|directory> [options]` | Неинтерактивно перенести или экспортировать выбранный граф страниц |
170
- | `ywtc reports list [--workdir <path>]` | Показать локальные отчёты от новых к старым |
171
- | `ywtc reports open [run-id\|last] [--workdir <path>]` | Открыть выбранный отчёт; `last` или отсутствие аргумента открывает последний корректный |
172
- | `ywtc update [--install] [--via npm\|brew]` | Проверить или установить обновление безопасным для текущего канала способом |
173
- | `ywtc --help`, `ywtc <command> --help` | Показать общую или командную справку |
174
- | `ywtc --version` | Показать версию |
136
+ | `ywtc init [-i] [-w <path>]` | Создать workspace или настроить оба подключения в TTY-мастере |
137
+ | `ywtc doctor [options]` | Проверить workspace; с source и destination — выполнить read-only preflight |
138
+ | `ywtc migrate -i` | Выбрать параметры, выполнить dry-run и при допустимом результате явно перейти к live |
139
+ | `ywtc migrate -s <locator> -d <locator\|directory> [options]` | Неинтерактивный перенос или экспорт |
140
+ | `ywtc reports list [-w <path>]` | Показать локальные отчёты от новых к старым |
141
+ | `ywtc reports open [run-id\|last] [-w <path>]` | Открыть выбранный или последний корректный отчёт |
142
+ | `ywtc update [-i] [-c npm\|brew]` | Проверить или установить обновление безопасным для текущего канала способом |
175
143
 
176
144
  ### Опции
177
145
 
178
- | Полная опция | Short | Команды | Обязательность / значения | Назначение |
179
- | --- | --- | --- | --- | --- |
180
- | `--interactive` | `-i` | `init`, `migrate` | требует stdin/stdout TTY | Запустить обязательный мастер настройки или миграции |
181
- | `--workdir <path>` | `-w` | `init`, `doctor`, `migrate`, `reports` | config в CWD или `~/.ywtc` | Явно выбрать workspace; поддерживается `~/...` |
182
- | `--source <value>` | `-s` | `doctor`, `migrate` | обязательно для неинтерактивного `migrate`; в `doctor` вместе с destination | URL, page ID или Yandex slug |
183
- | `--destination <value>` | `-d` | `doctor`, `migrate` | обязательно для неинтерактивного `migrate`; в `doctor` вместе с source | Родительская страница или каталог экспорта |
184
- | `--source-profile <name>` | `-S` | `doctor`, `migrate` | при неоднозначном коротком locator | Профиль source из `connections` |
185
- | `--destination-profile <name>` | `-D` | `doctor`, `migrate` | при неоднозначном remote locator | Профиль destination; несовместим с файловым экспортом |
186
- | `--scope <mode>` | `-m` | `doctor`, `migrate` | `page`, `subtree` (default), `linked` | Граница выбора страниц |
187
- | `--source-status <status>` | `-t` | `doctor`, `migrate` | `all` (default) или `current` | Статус автоматически обнаруживаемых страниц; явно заданный root включается всегда |
188
- | `--comments` / `--no-comments` | `-C` / `-N` | `doctor`, `migrate` | комментарии включены по умолчанию | Архивировать page comments или полностью отключить их чтение и запись |
189
- | `--format <format>` | `-f` | `doctor`, `migrate` | `markdown` или `html` | Делает destination файловым каталогом |
190
- | `--archive` | `-a` | `migrate` | только с файловым destination | Дополнительно создать ZIP рядом с каталогом |
191
- | `--dry-run` | `-n` | `migrate` | default `false`; default-действие wizard | Discovery и план без записи в destination |
192
- | `--fresh` | `-F` | `migrate` | default `false` | Игнорировать mappings текущего state |
193
- | `--open-report` | `-o` | `migrate` | default `false` | Открыть итоговый HTML-отчёт; ошибка браузера не меняет результат миграции |
194
- | `--concurrency <n>` | `-j` | `migrate` | `1..64`; иначе config default | Общая параллельность; профильные лимиты сохраняются |
195
- | `--state <path>` | `-r` | `migrate` | внутри workspace | Явный state вместо автоматического |
196
- | `--install` | `-i` | `update` | default `false` | Установить найденное обновление |
197
- | `--via <channel>` | `-c` | `update` | `npm` или `brew` | Явно выбрать совместимый канал обновления |
198
- | `--help` | `-h` | CLI и команды | необязательно | Справка |
199
- | `--version` | `-v` | CLI | необязательно | Версия |
200
-
201
- Одинаковые short-алиасы относятся только к своей команде: например, `migrate -i` запускает wizard, а `update -i` устанавливает обновление. В интерактивном режиме переданные опции становятся редактируемыми начальными значениями; без него `source` и `destination` обязательны.
202
-
203
- ### Локаторы
204
-
205
- - Yandex Wiki: полный URL, числовой page ID или slug, например `team/start`.
206
- - Confluence: числовой page ID, URL с `pageId=<id>` либо URL с `/pages/<id>` или `/content/<id>`.
207
- - Полный URL автоматически выбирает профиль по нормализованному base URL.
208
- - Короткий ID/slug выбирается автоматически только при единственном подходящем профиле; иначе нужен `--source-profile` или `--destination-profile`.
209
- - Каталог является файловой destination только вместе с `--format`.
210
-
211
- ### Scope
212
-
213
- - `page` — только исходная страница.
214
- - `subtree` — страница и все доступные структурные потомки до последнего уровня; default. С `all` Yandex Wiki включает `actual` и `obsolete`, а с `current` — только `actual`. Confluence переносит страницы, доступные через hierarchy API; archived, trashed и historical versions могут не возвращаться этим API.
215
- - `linked` — детерминированный BFS по внутренним ссылкам и page/include references до фиксированной точки. Циклы завершаются безопасно, каждая страница обрабатывается один раз; внешние и недоступные ссылки не обходятся и попадают в отчёт.
216
-
217
- ## Частые примеры
146
+ | Полная / short | Команды | Значения и назначение |
147
+ | --- | --- | --- |
148
+ | `--interactive`, `-i` | `init`, `migrate` | TTY-мастер; в `migrate` переданные опции становятся редактируемыми defaults |
149
+ | `--workdir`, `-w` | `init`, `doctor`, `migrate`, `reports` | Явный workspace; поддерживается `~/...` |
150
+ | `--source`, `-s` | `doctor`, `migrate` | URL, page ID или Yandex slug; обязателен в неинтерактивном `migrate` |
151
+ | `--destination`, `-d` | `doctor`, `migrate` | Родительская страница или каталог; обязателен в неинтерактивном `migrate` |
152
+ | `--source-profile`, `-S` | `doctor`, `migrate` | Имя source-профиля при неоднозначном коротком locator |
153
+ | `--destination-profile`, `-D` | `doctor`, `migrate` | Имя remote destination-профиля; запрещён для файлового экспорта |
154
+ | `--scope`, `-m` | `doctor`, `migrate` | `page`, `subtree` (default), `linked` |
155
+ | `--source-status`, `-t` | `doctor`, `migrate` | `all` (default) или `current`; root включается всегда |
156
+ | `--comments`, `-C` / `--no-comments`, `-N` | `doctor`, `migrate` | Комментарии включены по умолчанию; `-N` исключает все comment API calls |
157
+ | `--format`, `-f` | `doctor`, `migrate` | `markdown` или `html`; делает destination файловым |
158
+ | `--archive`, `-a` | `migrate` | Дополнительный ZIP для файлового экспорта |
159
+ | `--dry-run`, `-n` | `migrate` | Полный discovery/render без destination writes |
160
+ | `--fresh`, `-F` | `migrate` | Игнорировать mappings; существующий live-state сохранить как backup |
161
+ | `--open-report`, `-o` | `migrate` | Открыть итоговый HTML; ошибка opener не меняет outcome переноса |
162
+ | `--concurrency`, `-j` | `migrate` | `1..64`; иначе `defaults.concurrency` |
163
+ | `--state`, `-r` | `migrate` | Явный state path внутри workspace |
164
+ | `--install`, `-i` | `update` | Установить найденное обновление |
165
+ | `--via`, `-c` | `update` | `npm` или `brew` |
166
+ | `--help`, `-h` / `--version`, `-v` | CLI | Справка / версия |
167
+
168
+ Short-алиасы локальны для команды: `migrate -i` запускает мастер, `update -i` устанавливает обновление.
169
+
170
+ ### Locators и выбор страниц
171
+
172
+ - Yandex Wiki: полный URL, числовой page ID или slug вида `team/start`.
173
+ - Confluence: числовой page ID, URL с `pageId=<id>`, `/pages/<id>` или `/content/<id>`.
174
+ - Полный URL выбирает профиль по нормализованному base URL. Для неоднозначного ID/slug укажите профиль явно.
175
+ - Каталог считается destination только с `--format`.
176
+
177
+ | Scope | Выбор |
178
+ | --- | --- |
179
+ | `page` | Только root |
180
+ | `subtree` | Root и все доступные структурные descendants до последнего уровня; default |
181
+ | `linked` | Детерминированный BFS по внутренним ссылкам и page/include references; циклы завершаются безопасно |
182
+
183
+ `--source-status all` включает все доступные descendants: в Yandex Wiki — `actual` и `obsolete`; `current` оставляет только `actual/current`. Confluence зависит от hierarchy API и может не возвращать archived, trashed и historical versions.
184
+
185
+ ### Примеры
218
186
 
219
187
  ```bash
220
- # Перенести всё структурное поддерево
221
- ywtc migrate --source https://wiki.example.com/team/start \
222
- --destination https://confluence.example.com/confluence/pages/viewpage.action?pageId=123
188
+ # Перенести структурное поддерево
189
+ ywtc migrate -s https://wiki.example.com/team/start \
190
+ -d https://confluence.example.com/confluence/pages/viewpage.action?pageId=123
223
191
 
224
- # Перенести граф рекурсивно связанных страниц
225
- ywtc migrate --source https://wiki.example.com/team/start \
226
- --destination https://confluence.example.com/confluence/pages/viewpage.action?pageId=123 \
227
- --scope linked
192
+ # Перенести рекурсивно связанные страницы
193
+ ywtc migrate -s https://wiki.example.com/team/start \
194
+ -d https://confluence.example.com/confluence/pages/viewpage.action?pageId=123 \
195
+ -m linked
228
196
 
229
- # Создать автономный HTML-экспорт и ZIP
230
- ywtc migrate --source https://wiki.example.com/team/start \
231
- --destination ./exports/knowledge-base \
232
- --format html --archive
197
+ # Создать автономный HTML и ZIP
198
+ ywtc migrate -s https://wiki.example.com/team/start \
199
+ -d ./exports/knowledge-base -f html -a
233
200
 
234
201
  # Открыть последний корректный отчёт
235
202
  ywtc reports open last
236
203
  ```
237
204
 
238
- Wizard проверяет только доступность API и авторизацию без страниц и внешних записей. `doctor` принимает те же endpoints, profiles, `scope`, `source-status` и `format`: без endpoints он проверяет workspace, конфигурацию и секреты, а с обоими endpoints выполняет page-specific read-only capability-preflight.
239
-
240
205
  ## Файловый экспорт
241
206
 
242
- Markdown создаёт `index.md`, `pages/`, `attachments/`, `.ywtc-export.json` и, при деградациях, `_source/`. HTML создаёт автономный адаптивный сайт с локальным `assets/site.css`; он работает через `file://` и на static hosting без CDN или внешнего runtime.
243
-
244
- При включённых комментариях каждая страница получает секцию `Комментарии` с раскрываемыми ветками. Связанные из комментариев файлы находятся в одном ZIP рядом с attachments страницы; `manifest.json` внутри ZIP связывает source comment ID, исходную ссылку, исходное и архивное имя, размер и SHA-256.
245
-
246
- Экспорт сначала строится в staging-каталоге. Существующий каталог заменяется только при строгом актуальном manifest с `tool: ywtc` и той же canonical identity, а прежний каталог сохраняется как timestamped backup. `--archive` оставляет каталог и создаёт новый ZIP, не перезаписывая существующий архив.
247
-
248
- ## State
207
+ Markdown создаёт `index.md`, `pages/`, `attachments/` и `.ywtc-export.json`. HTML создаёт автономный адаптивный сайт с локальным CSS, который работает через `file://` и на static hosting без CDN или внешнего runtime. `_source/` появляется только для страниц, которым нужен raw snapshot.
249
208
 
250
- По умолчанию state хранится в `<workdir>/.states/<automatic-id>.json`. ID строится из канонических профилей и ID source/destination, а для файлового экспорта также из формата; форма locator, `scope` и `source-status` на ID не влияют. State имеет единственный строгий актуальный формат без поля версии. Несоответствующий файл не преобразуется и не изменяется. Относительный `--state` разрешается внутри workspace, выход за его границы запрещён. Live-run получает exclusive lock этого state: параллельный процесс останавливается до записей в destination, а доказанно stale локальный lock восстанавливается автоматически.
209
+ Внутренние ссылки и resources становятся относительными. Комментарии входят в страницу раскрываемыми ветками; явно связанные с ними файлы находятся в одном ZIP с `manifest.json`.
251
210
 
252
- ### Повторные запуски
211
+ Экспорт строится в соседнем staging-каталоге. Существующий каталог заменяется только при актуальном manifest с `tool: ywtc` и той же canonical identity; предыдущая версия сохраняется как timestamped backup. `--archive` оставляет каталог и создаёт новый ZIP, не перезаписывая существующий.
253
212
 
254
- - Одинаковые source и destination автоматически подхватывают один state независимо от формы URL/ID/slug.
255
- - Переключение `current → all` расширяет тот же state новыми страницами без дубликатов; обратное переключение не удаляет mappings вне текущего выбора.
256
- - Подтверждённая state-mapping означает, что source авторитетен: отличающийся body, title или parent mapped-страницы обновляется поверх актуальной destination-версии, а прежнее содержимое остаётся в истории провайдера.
257
- - Если ранее страница была создана под временно ближайшим выбранным предком, повторный запуск перемещает mapped-страницу под найденного родителя до обработки потомков независимо от изменений её body.
258
- - Уже сопоставленные страницы и вложения сверяются по ID, фактическому размеру и SHA-256; проверенный cache повторно не скачивается.
259
- - Неудачные mappings вложений автоматически получают безопасные уникальные имена и повторяются без `--fresh`.
260
- - Временный `404` подтверждённой destination-страницы повторяется с backoff; устойчиво пропавшая mapping восстанавливается под ожидаемым родителем с сохранением прежнего ID в state.
261
- - Страница с прежним неизменённым служебным placeholder ywtc автоматически получает полноценный source-derived контент.
262
- - Ошибка отдельного файла оставляет полный текст и source-ссылку, фиксирует `partial` и повторяет ресурс при следующем запуске.
263
- - Неизменённые архивы комментариев и ZIP проверяются и переиспользуются без дубликатов. Mapped Confluence-архив обновляется новой версией из source, а Yandex Wiki получает новую архивную ревизию, поскольку Public API не предоставляет update comments.
264
- - Удалённый mapped-комментарий создаётся заново. Исчезнувшие из доступного source API комментарии отмечаются `stale` и автоматически не удаляются.
265
- - Запуск с `--no-comments` не обращается к comment API и не удаляет ранее созданные архивы; следующий обычный запуск дополнит тот же state.
266
- - `conflict` используется только при доказанной неоднозначности immutable ownership/identity: несколько source mappings на один destination ID, несовпадение возвращённого immutable ID или несколько равноправных ownership-кандидатов. Версия, title, URL, slug, parent, fingerprint, HTTP `409`, слово `conflict` в сообщении и коллизия имени сами по себе конфликтом не являются.
267
- - `--fresh` игнорирует mappings; перед live-run прежний state сохраняется как backup, а destination может получить новые объекты.
268
- - Удалённые из source объекты автоматически не удаляются из destination.
213
+ ## State и повторные запуски
269
214
 
270
- При SIGINT/SIGTERM новые задачи не ставятся, активные безопасные операции завершаются, state и отчёт сохраняются. Коды выхода: `0` — completed; `1` — partial или verification failure; `2` — usage/config/preflight; `130`/`143` — остановка сигналом.
215
+ State находится в `<workdir>/.states/<automatic-id>.json`. ID зависит от канонических профилей и page IDs, а для экспорта — ещё от формата; URL/ID/slug, `scope` и `source-status` его не меняют. Относительный `--state` разрешается только внутри workspace.
271
216
 
272
- ## Отчёты
217
+ - Повтор одинакового направления подхватывает mappings, cache и незавершённые операции без дубликатов.
218
+ - Для доказанной mapping source авторитетен: body, title и parent обновляются поверх текущей destination-версии, а прежнее содержимое остаётся в истории. Unmapped и неоднозначно принадлежащие объекты не перезаписываются.
219
+ - Неверная иерархия исправляется сверху вниз; временные `404` повторяются, пропавшая mapped-страница восстанавливается под ожидаемым родителем без удаления старого объекта.
220
+ - Файлы согласуются по immutable ID, размеру и SHA-256; проверенный cache переиспользуется, занятые имена получают стабильный суффикс.
221
+ - Комментарии и их ZIP проверяются и переиспользуются. Confluence-архив обновляется версией, Yandex Wiki получает новую ревизию; исчезнувший source-архив сохраняется как stale.
222
+ - `current → all` расширяет тот же state; обратное переключение не удаляет прежние mappings. Удаление в source также не удаляет destination.
223
+ - `--fresh` игнорирует mappings и сохраняет прежний state как backup; destination при этом может получить новые объекты.
273
224
 
274
- Каждый запуск создаёт `<workdir>/.states/reports/<run-id>/index.html` и очищенный `report.json`, затем печатает run ID, `file://` URL и команду повторного открытия. `--open-report` открывает отчёт сразу; `ywtc reports list` показывает историю, `ywtc reports open <run-id>` — выбранный запуск, а `ywtc reports open last` или `ywtc reports open` — последний корректный.
225
+ Live-run использует exclusive lock; stale lock восстанавливается. При SIGINT/SIGTERM новые задачи не запускаются, безопасные активные операции завершаются, state и отчёт сохраняются. Коды выхода: `0` — completed, `1` — partial/verification failure, `2` — usage/config/preflight, `130`/`143` — сигнал.
275
226
 
276
- Автономный HTML-отчёт работает без сети. Компактный Mantine-интерфейс объединяет статус, progress, source/destination-сводку и ссылки на результат, state и `report.json`. Нулевые необязательные счётчики, пустые секции сводки и пустые вкладки деталей скрываются; обязательные totals, статусы и идентификаторы остаются видимыми.
227
+ ## Отчёты и статусы
277
228
 
278
- Ниже находится раскрытое дерево исходной иерархии, включая исключённые страницы; доступны поиск, фильтры проблем и прямые ссылки на source/destination. Строка страницы открывает только доступные вкладки файлов, комментариев, сравнения и проблем. Ошибки и зависимые `blocked` объекты подсвечиваются в дереве и объясняются в деталях. RU/EN и system/light/dark переключаются иконками; выбор сохраняется локально. Интерфейс адаптирован для мобильного экрана.
229
+ Каждый запуск создаёт `<workdir>/.states/reports/<run-id>/index.html` и очищенный `report.json`, затем печатает URL и команду открытия. Используйте `--open-report`, `ywtc reports list` или `ywtc reports open [run-id|last]`; без selector `open` также выбирает последний корректный отчёт.
279
230
 
280
- HTML/JSON, итог терминала и `reports list` используют одинаковые счётчики. Известный source volume отделён от подтверждённых transferred bytes; неизвестные размеры отмечены явно. `report.json` не содержит содержимое страниц, тексты комментариев или preview HTML — они остаются только в локальном `index.html`.
231
+ Автономный отчёт показывает только ненулевые показатели, канонические source/destination, исходную иерархию, исключённые страницы и проблемы. Дерево поддерживает поиск и фильтры; детали страницы содержат доступные files, comments, side-by-side comparison и диагностику. RU/EN и system/light/dark переключаются иконками. `report.json` не содержит body страниц, тексты комментариев или preview HTML.
281
232
 
282
- Качество преобразования учитывается отдельно: normalization — безопасная разница сериализации; adaptation — полное эквивалентное представление, например Grid → static table или колонки другой ширины; degradation — доказанная неполнота, влияющая на `partial`; preserved external reference — исходный внешний URL, который и должен остаться внешним. Normalization и adaptation не увеличивают warnings и не переводят запуск в `completed-with-warnings`.
233
+ ### Outcomes объектов
283
234
 
284
- ### Статусы переноса
285
-
286
- Статусы страниц:
287
-
288
- | Статус | Смысл | Данные записаны | Что делать |
289
- |---|---|---:|---|
290
- | `complete` | Страница и связанные объекты записаны и проверены | Да | Ничего |
291
- | `partial` | Часть данных, managed-ресурсов, комментариев или значимой структуры отсутствует либо результат не проверен | Да | Посмотреть degradation в отчёте; повторить запуск для retryable-проблем |
292
- | `failed` | Операция страницы началась, но корректная запись или проверка не удалась | Возможно частично | Исправить root error и повторить ту же миграцию |
293
- | `blocked` | Страница не запускалась из-за недоступного failed/conflict родителя или другой зависимости | Нет в этом запуске | Исправить указанную upstream-ошибку и повторить запуск |
294
- | `conflict` | Immutable ownership/identity destination доказанно неоднозначна, в отчёте перечислены кандидаты | Нет автоматической перезаписи | Проверить candidate IDs и устранить неоднозначное сопоставление |
295
- | `planned` | Объект рассчитан в `--dry-run`; запись не выполнялась | Нет | Убрать `--dry-run` для переноса |
296
- | `not-started` | Live-run остановился до начала независимой операции | Нет | Повторить ту же миграцию |
297
-
298
- Статусы файлов:
235
+ | Outcome | Объекты | Значение и действие |
236
+ | --- | --- | --- |
237
+ | `complete` | страницы, файлы, comment archives | Записано и проверено; действий не требуется |
238
+ | `partial` | страницы, файлы, comment archives | Основное представление доступно, но часть данных отсутствует или не проверена; изучить degradation и повторить retryable-операцию |
239
+ | `failed` | все | Операция началась, но корректная запись или проверка не получилась; исправить root error и повторить запуск |
240
+ | `blocked` | страницы, файлы, comment archives | Операция не начиналась из-за недоступного parent/dependency; сначала исправить upstream failure/conflict |
241
+ | `conflict` | mapped-объекты | Immutable ownership/identity неоднозначна; проверить candidate IDs. Обычная новая версия, ручное изменение, title collision или HTTP `409` конфликтом не считаются |
242
+ | `planned` | все | Объект рассчитан в dry-run, записи не было; запустить live |
243
+ | `not-started` | все | Live-run остановился до независимой операции; повторить запуск |
299
244
 
300
- | Статус | Смысл | Данные записаны | Что делать |
301
- |---|---|---:|---|
302
- | `complete` | Файл загружен и проверен | Да | Ничего |
303
- | `partial` | Файл доступен через сохранённый fallback, но нативная передача неполна | Частично | Проверить fallback и повторить retryable-операцию |
304
- | `failed` | Download, upload или verification файла выполнялся и завершился ошибкой | Возможно частично | Проверить причину и повторить запуск |
305
- | `blocked` | Файл не обрабатывался, потому что destination-страница недоступна | Нет в этом запуске | Сначала устранить указанную ошибку страницы |
306
- | `planned` | Файл только запланирован в `--dry-run` | Нет | Запустить без `--dry-run` |
307
- | `not-started` | Live-run прерван до начала обработки файла | Нет | Повторить ту же миграцию |
245
+ ### Качество преобразования
308
246
 
309
- `failed` означает неудавшуюся попытку самого объекта; `blocked` — сознательно не начатую операцию из-за upstream-зависимости. Поэтому зависимые блокировки показываются отдельно и не увеличивают число root errors.
247
+ | Категория | Влияние |
248
+ | --- | --- |
249
+ | Normalization | Безопасная разница сериализации или нативный эквивалент; остаётся `complete` |
250
+ | Adaptation | Другое представление с проверенной полнотой, например Grid → static table; остаётся `complete` |
251
+ | Preserved external reference | Внешний URL сохранён как внешний и не требует копирования; остаётся `complete` |
252
+ | Degradation | Данные или значимая структура отсутствуют либо полнота не доказана; даёт `partial` |
253
+ | Warning | Требует внимания, но сам по себе не доказывает потерю |
254
+ | Error | Неудавшаяся API/record/verification операция; итог зависит от сохранности полного body и объекта |
310
255
 
311
- Итоговый статус запуска: `completed`, `completed-with-warnings`, `partial`, `failed`, `cancelled` или `interrupted`. Provider-aware verification допускает безопасные различия сериализации и полные adaptations. Только потеря текста, ссылки, ячейки таблицы, кода, managed-изображения, вложения, комментария, anchor или невозможность доказать полноту ухудшает статус. Технический статус `skeleton-created` уже содержит source-derived bootstrap, а не progress-placeholder.
256
+ Итог запуска: `completed`, `completed-with-warnings`, `partial`, `failed`, `cancelled` или `interrupted`. HTML, JSON, terminal summary и `reports list` используют одинаковые totals; зависимые `blocked` объекты не считаются отдельными root errors.
312
257
 
313
258
  ## Разработка
314
259
 
@@ -320,6 +265,6 @@ npm run workspace:init
320
265
  npm run check
321
266
  ```
322
267
 
323
- `npm run check` запускает проверку репозитория и секретов, production audit уровня high/critical, TypeScript, Biome, Knip, тесты, сборку, проверку npm-пакета и строгую OpenSpec-валидацию. Любое изменение проходит полный OpenSpec-цикл из [`AGENTS.md`](AGENTS.md).
268
+ `npm run check` запускает release hygiene и security audit, TypeScript, Biome, Knip, Vitest, Playwright, сборку, package smoke-test и строгую OpenSpec-валидацию. Любое изменение проходит цикл из [`AGENTS.md`](AGENTS.md).
324
269
 
325
- Release Please рассчитывает SemVer из Conventional Commits. После merge release PR GitHub Actions проверяет релиз, публикует GitHub Release и npm-пакет через OIDC provenance, затем обновляет и проверяет Homebrew-формулу. Версии и changelog вручную не изменяются.
270
+ Release Please рассчитывает SemVer из Conventional Commits. После merge release PR GitHub Actions публикует GitHub Release и npm-пакет с OIDC provenance, затем генерирует, устанавливает и тестирует Homebrew-формулу.