@rt-tools/agent-kit 0.23.0 → 0.24.0

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.
Files changed (61) hide show
  1. package/README.md +8 -2
  2. package/assets/checks/board.github.mjs +1 -1
  3. package/assets/checks/check-board.github.mjs +14 -0
  4. package/assets/checks/check-doc-paths.mjs +24 -5
  5. package/assets/checks/check-file-size.mjs +8 -2
  6. package/assets/checks/check-prose-style.mjs +10 -1
  7. package/assets/defaults/gate-map.sh +13 -0
  8. package/assets/defaults/project.sh +10 -0
  9. package/assets/defaults/shell.sh +18 -3
  10. package/assets/hooks/browser-guard-device-id.sh +42 -12
  11. package/assets/hooks/dispatch.sh +40 -9
  12. package/assets/hooks/docs-guard.sh +10 -0
  13. package/assets/hooks/exam-guard.sh +66 -16
  14. package/assets/hooks/git-guard-delivery-draft.sh +78 -0
  15. package/assets/hooks/git-guard-delivery.sh +49 -111
  16. package/assets/hooks/git-guard-main.sh +39 -4
  17. package/assets/hooks/git-guard-push-tests.sh +49 -3
  18. package/assets/hooks/hook-input.sh +17 -6
  19. package/assets/hooks/rule-source-guard.sh +11 -0
  20. package/assets/hooks/stand-login-guard.sh +101 -0
  21. package/assets/hooks/write-targets.sh +37 -4
  22. package/assets/laws/verifiability.md +12 -2
  23. package/assets/laws/work-conduct.md +59 -65
  24. package/assets/patterns/browser-verification-measure.md +41 -1
  25. package/assets/patterns/browser-verification-stand.md +56 -15
  26. package/assets/patterns/doc-style-human.md +75 -0
  27. package/assets/patterns/git-workflow-commit.azure.md +12 -0
  28. package/assets/patterns/git-workflow-commit.github.md +16 -3
  29. package/assets/patterns/git-workflow-commit.gitlab.md +12 -0
  30. package/assets/patterns/git-workflow-merge.md +8 -0
  31. package/assets/patterns/task-flow-start.md +1 -1
  32. package/assets/patterns/testing-e2e.md +18 -8
  33. package/assets/pitfalls/task-flow.md +40 -40
  34. package/assets/rules/browser-verification.md +29 -3
  35. package/assets/rules/doc-style.md +36 -0
  36. package/assets/rules/git-workflow.github.md +20 -23
  37. package/assets/rules/reuse-first.md +8 -2
  38. package/assets/rules/styling-bem.md +8 -1
  39. package/assets/rules/task-flow.md +73 -73
  40. package/assets/rules/testing.md +21 -0
  41. package/assets/skills/agent-kit.md +60 -70
  42. package/lib/commands.d.ts.map +1 -1
  43. package/lib/commands.js +63 -2
  44. package/lib/commands.js.map +1 -1
  45. package/lib/enroll.d.ts.map +1 -1
  46. package/lib/enroll.js +1 -1
  47. package/lib/enroll.js.map +1 -1
  48. package/lib/observations.d.ts +10 -1
  49. package/lib/observations.d.ts.map +1 -1
  50. package/lib/observations.js +1 -0
  51. package/lib/observations.js.map +1 -1
  52. package/lib/override-marks.d.ts +24 -0
  53. package/lib/override-marks.d.ts.map +1 -0
  54. package/lib/override-marks.js +98 -0
  55. package/lib/override-marks.js.map +1 -0
  56. package/lib/shipment.d.ts.map +1 -1
  57. package/lib/shipment.js +1 -1
  58. package/lib/shipment.js.map +1 -1
  59. package/package.json +1 -1
  60. package/rt-tools-agent-kit-0.24.0.tgz +0 -0
  61. package/rt-tools-agent-kit-0.23.0.tgz +0 -0
@@ -120,6 +120,14 @@ flowchart TD
120
120
  каталог, любая своя ошибка — гард выходит нулём и пропускает: сломанная проверка не имеет права
121
121
  заклинить работу. Объявляется это строкой `FAIL-OPEN` в шапке самого гарда, рядом с
122
122
  перечислением случаев, и туда же дописывается новый случай, когда он находится.
123
+ - **Гард, не узнавший вызов, молчит так же, как исправный.** Нулевой выход бывает двух родов: гард
124
+ сломался и отпустил намеренно — это объявлено в его шапке, — либо он не признал в команде своего
125
+ дела и до проверки не дошёл вовсе. Снаружи они неотличимы, а второй не объявлен нигде и не
126
+ оставляет следа. Отсюда два следствия. Признак вызова обязан ошибаться в сторону лишнего
127
+ срабатывания: сработавший на лишнем виден сразу и правится, не узнавший — не виден никогда. И
128
+ принятый в дереве способ звать команду — полным путём, через обёртку, с подстановкой переменных —
129
+ входит в признак наравне с голым именем: обход, которым команду зовут каждый день, ровно там гард
130
+ и слепнет.
123
131
  - **Список известного у проверки именной и объясняет себя сам.** Первым полем перечня стоит имя
124
132
  проверки и слово о том, что перечисленное отказом не считается. Дальше либо два ключа — принятое
125
133
  остаётся навсегда, долг накоплен к заведению проверки и только сокращается, — либо столько
@@ -186,6 +194,19 @@ flowchart TD
186
194
  по-прежнему, и плывущее значение внутри него двигает соседей мимо маски. Там, где размер узла
187
195
  считается по содержимому — ячейка таблицы, надпись, растягивающая кнопку, — плывущее лечится в
188
196
  данных стенда постоянным значением, и тогда маска не нужна вовсе.
197
+ - **Постоянным делается не только время, но и всё, что приложение из него вывело.** Приложение
198
+ считает от своих часов и производное — ключ месяца, срок, признак свежести, — и считает его в
199
+ минуту записи. Правка времён, идущая после записи, производного не двигает: оно посчитано раньше
200
+ и лежит в соседней колонке. Расхождения при этом не наступает месяцами, а потом набор краснеет в
201
+ день, когда в дерево не внесли ни строки. Признак у промаха свой и виден сравнением двух колонок:
202
+ производное перестало сходиться с тем, из чего его обязаны были вывести.
203
+ - **Засев проверяет себя сам, а не полагается на кадр.** Кадр говорит «стало другим» и молчит о
204
+ том, почему; отказ засева называет причину словами и приходит до того, как снят хоть один кадр.
205
+ Признак берётся верный в любой день прогона: данные стенда — прошлое, поэтому значение времени,
206
+ попавшее на день прогона или позже, посчитано часами машины, а засевом не закреплено. Нарочно
207
+ будущее отделяется границей и называется отдельно. Судятся при этом временные колонки всех
208
+ таблиц, которые читают экраны, а не только показанные сегодня: столбец выводят на экран одной
209
+ строкой разметки, и вспомнить при этом про засев некому.
189
210
 
190
211
  ## Чего из закона здесь нет
191
212
 
@@ -53,24 +53,21 @@ description: Переносимый слой правил агента — за
53
53
  **Подъём версии пакета и раскладка едут одним изменением.** Сверка раскладки стоит в гейте
54
54
  пуша: редакция, поднятая без раскладки, красит главную ветку и запирает дерево целиком.
55
55
 
56
- **Объявление хука раскладка кладёт вместе с самим хуком.** Гард зовёт не файл, а запись в
57
- настройке агента, и разложенный без неё он снаружи неотличим от работающего: файл лежит,
58
- коммитится, сверка зелёная а вызова, ради которого написано его тело, он не видит. Раскладка
59
- дописывает в настройку запись на каждое событие, которого там нет, и говорит, что дописала.
60
- Правка только прибавляет: ни одна стоящая запись не переписывается и не снимается, снятое
61
- деревом не возвращается, а настройку, которую не разобрать как JSON, пакет не трогает вовсе —
62
- там печатается готовый кусок и запись идёт рукой, как прежде.
56
+ **Объявление хука раскладка кладёт вместе с самим хуком.** Хук вызывается по записи в настройке
57
+ агента, и разложенный без неё снаружи неотличим от работающего. Раскладка дописывает запись на
58
+ каждое событие, которого в настройке нет, и сообщает об этом. Правка только добавляет: записи не
59
+ переписываются и не снимаются, снятое деревом не возвращается, а настройку, которую не разобрать
60
+ как JSON, пакет не трогает печатает готовый кусок для записи рукой.
63
61
 
64
62
  **Держит это гард места правки, а не память.** Правку файла с шапкой раскладки он отбивает в
65
63
  минуту правки и называет адрес: источник, если дерево его держит, иначе надстройку. Правит копию
66
- не только рука: форматтер дерева, дошедший до разложенного файла, переписывает его по-своему, и
67
- раскладка читает это ровно как правку руками. Снятие копии гард пропускает: снятый файл
68
- раскладка кладёт заново, и так эту поломку и чинят.
64
+ не только рука: форматтер дерева переписывает разложенный файл по-своему, и раскладка читает это
65
+ ровно как правку руками. Снятие копии гард пропускает снятый файл раскладка кладёт заново.
69
66
 
70
67
  **Надстройка правится по разделу, а не кладётся целиком.** Разделы в неё дописывают разные ветки
71
- и разные заходы, и положенная целиком она уносит все, которых эта правка не касалась: на их
72
- место молча возвращается пакетный текст. Держит это второй гард — он отбивает запись поверх непустой надстройки и называет
73
- размер того, что затрут: строки и число разделов. Дописывание в конец и правка по месту проходят.
68
+ и разные заходы, и положенная целиком она уносит все, которых эта правка не касалась. Держит это
69
+ второй гард — он отбивает запись поверх непустой надстройки и называет размер того, что затрут.
70
+ Дописывание в конец и правка по месту проходят.
74
71
 
75
72
  ## Команды
76
73
 
@@ -85,8 +82,7 @@ npx agent-kit adopt [файлы] # отдать пакету свой файл,
85
82
  ```
86
83
 
87
84
  Отдача откладывает прежнее содержимое рядом, с пометкой `.before-rt-kit`, и освобождает путь под
88
- раскладку; без имён отдаются все чужие файлы разом. Названа она здесь потому, что иначе её
89
- находят по тексту отказа раскладки — то есть в ту минуту, когда работа уже встала.
85
+ раскладку; без имён отдаются все чужие файлы разом.
90
86
 
91
87
  Часть команд слоя исполняет агент, а не программа: `/feedback` кладёт слово о правилах блоком в
92
88
  файл предложений, `/skill-curator` разбирает закрытую задачу, `/next-session` закрывает заход.
@@ -108,11 +104,10 @@ npx agent-kit adopt [файлы] # отдать пакету свой файл,
108
104
  cp -r node_modules/@rt-tools/agent-kit/assets /tmp/agent-kit-assets-<прежняя версия>
109
105
  ```
110
106
 
111
- 2. **Установка и раскладка.** Обычным порядком. Раскладка кладёт ту редакцию, которая **установлена**,
112
- а не ту, что объявило дерево: перепутать их легко — установленная остаётся от соседней ветки,
113
- где её как раз поднимали, и ложится целиком, молча, с тем же успешным выходом. Расхождение
114
- точного номера раскладка отбивает сама и называет обе редакции; починка поставить
115
- зависимости и повторить вызов.
107
+ 2. **Установка и раскладка.** Обычным порядком. Раскладка кладёт ту редакцию, которая
108
+ **установлена**, а не ту, что объявило дерево: установленная остаётся от соседней ветки и
109
+ ложится целиком, молча, с тем же успешным выходом. Расхождение точного номера раскладка
110
+ отбивает сама; починка поставить зависимости и повторить вызов.
116
111
  3. **Сверка замещённых разделов по снимку.** Какие разделы замещены, называет `doctor` — строкой
117
112
  «замещено надстройками разделов» и перечнем «ресурс · заголовок». Каждый из них читается в
118
113
  снимке и в новой редакции: что пакет дописал, дописывается в надстройку руками.
@@ -123,8 +118,7 @@ npx agent-kit adopt [файлы] # отдать пакету свой файл,
123
118
  этим раздел замещён. Готовая пара команд — в холодной части рядом.
124
119
 
125
120
  Дальше решение обычное: раздел, ради которого надстройка заводилась, остаётся замещённым, а
126
- раздел, чья причина ушла с исправленной редакцией, снимается — о том и говорит четвёртая строка
127
- предложения.
121
+ раздел, чья причина ушла с исправленной редакцией, снимается.
128
122
 
129
123
  ## Что пакет везёт, а что остаётся дереву
130
124
 
@@ -164,18 +158,16 @@ npx agent-kit adopt [файлы] # отдать пакету свой файл,
164
158
  и не загружено ни разу**: правило, которого никто не открыл, ничем себя не выдаёт.
165
159
 
166
160
  **Цена** — `agent-kit cost`. Сводка говорит, чем пользовались; цена — сколько это стоило: вес
167
- входа в работу, вес одного правила и вес всего слоя. Считается не файл, а то, что заход получает:
168
- описание приходит полем, словарь и карта хода — выводом хуков. Число сравнимо только со снятым
169
- той же командой.
161
+ входа в работу, вес одного правила и вес всего слоя. Считается не файл, а то, что заход получает.
162
+ Число сравнимо только со снятым той же командой.
170
163
 
171
164
  **Предложения** приходят двумя путями: разбор закрытой задачи — командой `/skill-curator` —
172
165
  приносит их пачкой, а слово, сказанное посреди работы, кладёт командой `/feedback` сам агент. Оба
173
166
  пишут в один файл дня и в одной форме; в сеть не ходит ни один — увозит их отправка.
174
167
 
175
168
  Каждая запись несёт четыре строки: **место** — куда правка встаёт в ресурсе, **повод** — что
176
- пошло не так без неё, **ближайшее** — точная цитата той строки ресурса, к которой это ближе
177
- всего, и чего она не покрывает, и **чем закрывается** — какие надстройки и добавки этого дерева
178
- снимаются, когда правка приедет редакцией пакета.
169
+ пошло не так без неё, **ближайшее** — точная цитата строки ресурса, к которой это ближе всего, и
170
+ **чем закрывается** — какие надстройки дерева снимаются, когда правка приедет редакцией пакета.
179
171
 
180
172
  Третья строка — единственная, которую проверяет машина: цитата ищется в ресурсе, и ненайденная
181
173
  отбивает блок. Ближайшего нет вовсе — так и пишется: «нет». Отбитый блок остаётся лежать с
@@ -185,46 +177,51 @@ npx agent-kit adopt [файлы] # отдать пакету свой файл,
185
177
  без неё она замещает уже исправленный раздел навсегда. Снимать нечего — так и пишется; пустой
186
178
  четвёртая строка не бывает.
187
179
 
188
- Каждому предложению ставится адрес: «пакет», «компаньон» или «дерево». Выгружаются они файлом в `.claude/rt-kit/proposals/`
189
- (форма — шаблон `proposal.md`), а `agent-kit propose` увозит в приём те, что адресованы
190
- пакету, вместе со сводкой и разборами происшествий. Адрес дерева в сводке или в тексте
191
- предложения отбивает отправку целиком.
180
+ Та же связь ставится и на саму надстройку комментарием разметки в её разделе:
181
+
182
+ <!-- rt-proposed: rules/task-flow.md · «статья целиком, как в предложении» · 2026-09-03 -->
183
+
184
+ Записи предложений в день обновления никто не открывает: на них ничто не указывает. Пометка не
185
+ видна в собранном тексте, переживает слияние по заголовкам и читается машиной: раскладка
186
+ перечисляет разделы, чья статья в новой редакции уже есть. Снимает их человек — в раздел могли
187
+ дописать и другое. Раздел без пометки считается постоянным.
188
+
189
+ Каждому предложению ставится адрес: «пакет», «компаньон» или «дерево». Выгружаются они файлом в
190
+ `.claude/rt-kit/proposals/` (форма — шаблон `proposal.md`), а `agent-kit propose` увозит в приём
191
+ те, что адресованы пакету, вместе со сводкой и разборами происшествий. Адрес дерева в сводке или
192
+ в тексте предложения отбивает отправку целиком.
192
193
 
193
194
  Приём — закрытая служба: сводка говорит о рабочих привычках команды, и в открытой очереди работ
194
195
  это выложено всему свету. Адрес приёма объявляется ключом `intake` в конфиге дерева, токен —
195
196
  ключом `token`, и лежит он вне дерева.
196
197
 
197
- Оба значения приходят от владельца приёма, а не придумываются потребителем: адрес он называет, а токен выдаёт
198
- одноразовым кодом приглашения — код заводит дерево в приёме и кладёт токен в файл ключа `token`; выданный в админке
199
- кладётся тем же входом и в сеть не идёт. До приглашения отправка отказывает по устройству, а не по недонастройке.
198
+ Оба значения приходят от владельца приёма, а не придумываются потребителем: адрес он называет, а
199
+ токен выдаёт одноразовым кодом приглашения — код заводит дерево в приёме и кладёт токен в файл
200
+ ключа `token`. До приглашения отправка отказывает по устройству, а не по недонастройке.
200
201
 
201
202
  **Признак дерева считает отправитель, а не человек.** Он выводится из адреса репозитория, и
202
- запись в приёме заводится именно им: дерево, заведённое своим словом, приёмник не узнаёт и
203
- отвечает отказом на каждой отправке. Что уедет и под каким признаком, печатает прогон вхолостую —
204
- единственный способ узнать признак до заведения записи.
203
+ запись в приёме заводится именно им: дерево, заведённое своим словом, приёмник не узнаёт. Что
204
+ уедет и под каким признаком, печатает прогон вхолостую.
205
205
 
206
- **Отметка об отправке — след для человека, а не хранилище состояния: она говорит, что запись в
207
- приёме есть, а не что её положил этот вызов.** Чистое дерево после отправки значит, что весь
208
- груз в приёме уже лежал, а не что отправка не сработала.
206
+ **Отметка об отправке — след для человека, а не хранилище состояния.** Чистое дерево после
207
+ отправки значит, что весь груз в приёме уже лежал, а не что отправка не сработала.
209
208
 
210
209
  Разбирают их там, где лежат правимые ресурсы и видно всех потребителей сразу, — а сюда
211
210
  приезжает ответ приёма о том, сколько записей легло.
212
211
 
213
212
  **Имя файла предложения в текстах дерева не называется.** Читателю чужого дерева оно не даёт
214
- ничего, а там, где каталог остаётся на машине автора, ссылка ведёт в пустоту и проверка путей
215
- краснеет. Текст репозитория говорит, кому предложение отправлено и о чём оно; ресурс пакета
216
- при этом называть можно — он в истории есть.
213
+ ничего, а ссылка на каталог с машины автора ведёт в пустоту и красит проверку путей. Текст
214
+ репозитория говорит, кому предложение отправлено и о чём оно; ресурс пакета называть можно.
217
215
 
218
216
  Предложение работу не выправляет. Оно лежит текстом, читается глазами и в контекст сам собой не
219
- приходит; цитата не становится правилом от того, что её произнесли. Закрытым предложение
220
- считается, только войдя в ресурс пакета: до этого на него не ссылаются как на действующее
221
- требование и не считают дырку закрытой.
217
+ приходит. Закрытым оно считается, только войдя в ресурс пакета: до этого на него не ссылаются как
218
+ на действующее требование и не считают дырку закрытой.
222
219
 
223
220
  **Слово владельца о предложении — «отправь», «заведи», «напиши пропозал» и любая другая форма
224
- того же — исполняется отправкой в тот же ход.** Сухой прогон отправкой не является: он
225
- показывает, что уехало бы, ничего не заводит и следа наружу не оставляет. Отметки, которыми
226
- отправка пачкает дерево, ложатся вторым коммитом в ту же ветку это их место, а не повод
227
- отложить. Стережёт это гард предложения на завершении хода.
221
+ того же — исполняется отправкой в тот же ход.** Сухой прогон отправкой не считается: он
222
+ показывает, что было бы отправлено, и следа наружу не оставляет. Отметки, которые отправка
223
+ оставляет в дереве, ложатся вторым коммитом в ту же ветку. Это проверяет гард предложения на
224
+ завершении хода.
228
225
 
229
226
  ## Установка туда, где уже всё своё
230
227
 
@@ -276,23 +273,16 @@ npx agent-kit adopt [файлы] # отдать пакету свой файл,
276
273
  целиком, до первой реплики, и оттого он выглядит обычным документом дерева; шапка у него есть,
277
274
  но читается служебной строкой. Новое слово идёт в надстройку словаря, своим разделом.
278
275
 
279
- - **Запись файла командой оболочки судится по всем путям, названным в её теле.** Гейт вынимает
280
- пути из текста команды, а тело документа читает целиком, как только в команде встречается имя
281
- интерпретатора, — и строка запуска первой строкой записываемого файла возвращает его туда сама.
282
- Строка импорта разложенного модуля требует тогда правило пакетного слоя наравне с правилом
283
- самого файла, а требуется за раз одно: два отказа подряд, и каждый уносит уже написанное тело.
284
- Инструмент правки судится одним своим путём и переписывать тело не заставляет; перенаправление
285
- оболочки остаётся для того, что файлом дерева не станет.
286
- - **Своё, стоящее рядом с разложенным, повторяет его механику молча.** Проверка, гард и утилита
287
- дерева лежат в тех же каталогах, что и пакетные, а общий разбор списка известного, корни
288
- исходников и снимок долга приезжают модулем настройки проверок. Второе такое же заводится без
289
- сигнала: повтора не видит ни сверка раскладки — файл не разложен, — ни проверка повторов,
290
- которая ищет совпадение текста. Признак один, и он читается: до того как в своей проверке
291
- заводится разбор списка, чтение настройки или сравнение с накопленным, смотрят, что
292
- экспортирует модуль настройки проверок.
276
+ - **Запись файла командой оболочки проверяется по всем путям, названным в её теле.** Гейт
277
+ вынимает пути из текста команды и читает тело документа целиком, если в команде есть имя
278
+ интерпретатора; строка импорта разложенного модуля тогда требует второе правило, а требуется
279
+ за раз одно два отказа подряд, и каждый теряет написанное тело. Инструмент правки
280
+ проверяется одним своим путём; перенаправление оболочки для того, что файлом дерева не станет.
281
+ - **Своё, стоящее рядом с разложенным, повторяет его механику молча.** Разбор списка известного,
282
+ корни исходников и снимок долга даёт модуль настройки проверок; второй такой же разбор в своей
283
+ проверке не видит ни сверка раскладки, ни проверка повторов. Перед тем как завести своё, смотрят,
284
+ что экспортирует модуль настройки проверок.
293
285
  - **Правило, загруженное инструментом, бывает показано не целиком, и обрыв ничем не помечен.**
294
- Длинный файл приезжает в контекст обрезанным по строке, а снаружи это выглядит концом: показанное
295
- кончается осмысленным пунктом. Бьёт обрыв ровно по хвосту, а хвост то место, где дерево
296
- отменяет умолчания пакета: разделы надстройки сливаются по совпавшему заголовку и новыми уходят
297
- в конец. Отсюда порядок: решение о порядке работы принимается после того, как показанные строки
298
- сверены с длиной файла одной командой, а расходятся они — файл дочитывается чтением.
286
+ Длинный файл приходит в контекст обрезанным по строке, а обрыв приходится на хвост — туда, где
287
+ разделы надстройки дописаны в конец. Показанные строки сверяются с длиной файла одной командой;
288
+ расходятся файл дочитывается чтением.
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/commands.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAuB7C,MAAM,WAAW,iBAAiB;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED,2FAA2F;AAC3F,MAAM,WAAW,YAAY;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IACpC;;;OAGG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CAC1B;AA2DD,+DAA+D;AAC/D,eAAO,MAAM,WAAW,EAAE,MAAyB,CAAC;AA0ZpD;;;;GAIG;AACH,wBAAgB,IAAI,CAChB,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,SAAS,MAAM,EAAO,EAC5B,QAAQ,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM,EAC/C,SAAS,GAAE,MAAW,GACvB,iBAAiB,CAgCnB;AAmKD,wBAAgB,IAAI,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,GAAG,iBAAiB,CA8DzE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,iBAAiB,CA+CpF;AAQD,0EAA0E;AAC1E,MAAM,WAAW,aAAa;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,8FAA8F;IAC9F,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;CAC1B;AA8JD;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,YAAY,EAAE,OAAO,EAAE,aAAa,GAAG,iBAAiB,CA6DlF;AA0BD,wBAAgB,MAAM,CAAC,GAAG,EAAE,YAAY,GAAG,iBAAiB,CAkF3D;AAED;;;;;GAKG;AACH,wBAAgB,IAAI,CAAC,GAAG,EAAE,YAAY,GAAG,iBAAiB,CA2DzD"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/commands.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAwB7C,MAAM,WAAW,iBAAiB;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED,2FAA2F;AAC3F,MAAM,WAAW,YAAY;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IACpC;;;OAGG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CAC1B;AA2DD,+DAA+D;AAC/D,eAAO,MAAM,WAAW,EAAE,MAAyB,CAAC;AA+apD;;;;GAIG;AACH,wBAAgB,IAAI,CAChB,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,SAAS,MAAM,EAAO,EAC5B,QAAQ,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM,EAC/C,SAAS,GAAE,MAAW,GACvB,iBAAiB,CAgCnB;AA0LD,wBAAgB,IAAI,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,GAAG,iBAAiB,CA+DzE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,iBAAiB,CA+CpF;AAQD,0EAA0E;AAC1E,MAAM,WAAW,aAAa;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,8FAA8F;IAC9F,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;CAC1B;AAoLD;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,YAAY,EAAE,OAAO,EAAE,aAAa,GAAG,iBAAiB,CA6DlF;AA0BD,wBAAgB,MAAM,CAAC,GAAG,EAAE,YAAY,GAAG,iBAAiB,CAkF3D;AAED;;;;;GAKG;AACH,wBAAgB,IAAI,CAAC,GAAG,EAAE,YAAY,GAAG,iBAAiB,CA2DzD"}
package/lib/commands.js CHANGED
@@ -14,6 +14,7 @@ import { CONFIG_PATH, DEFAULT_LAYOUT, KINDS, OVERRIDES_DIR, PROFILE_FILE, readCo
14
14
  import { hooksSection, SETTINGS_PATH } from './hooks-map.js';
15
15
  import { DEFAULT_DAYS, KEEP_DAYS, OBSERVATIONS_DIR, readObservations, summarize, } from './observations.js';
16
16
  import { isRefusal } from './plan.js';
17
+ import { staleOverrides } from './override-marks.js';
17
18
  import { pushGateLines } from './push-gate.js';
18
19
  import { laidOutSkills, treeSnapshot } from './snapshot.js';
19
20
  import { mergedBody, pendingOf, planSync, runSync } from './sync.js';
@@ -186,6 +187,25 @@ const holes = (result) => [...result.missing].map(([asset, names]) => {
186
187
  const written = names.map(holeOf).join(', ');
187
188
  return ` ${asset}: нет значений для ${written}`;
188
189
  });
190
+ /**
191
+ * Незаполненная дырка — состояние дерева, а не расхождение с пакетом.
192
+ *
193
+ * Расхождение говорит, что разложенное разошлось с редакцией; дырка без значения — что дерево
194
+ * ещё не описало своего: порты стенда, префикс компонентов, имя главной ветки. Один код возврата
195
+ * на оба состояния ставит дерево перед выбором между красным гейтом пуша и выдуманными числами в
196
+ * настройке, после чего подстановки теряют смысл.
197
+ *
198
+ * Раскладки это не касается: файл с дыркой на диск не кладётся, и `sync` отказывает по-прежнему —
199
+ * разложенное правило с `{{имя}}` посреди строки агент прочтёт как имя.
200
+ */
201
+ const holeWarningLines = (result) => result.missing.size
202
+ ? [
203
+ `дерево ещё не описало своего: ресурсов с незаполненными дырками ${result.missing.size}`,
204
+ ...holes(result),
205
+ ' — это описание дерева, а не расхождение с пакетом: значения идут ключом `vars` в `.claude/rt-kit.json`',
206
+ ' — до них ресурс не раскладывается, и на диске его нет',
207
+ ]
208
+ : [];
189
209
  const unfilled = (result) => result.companions.filter(isUnfilled);
190
210
  /**
191
211
  * Строка про компаньон, которому нечего сказать.
@@ -387,6 +407,7 @@ const strayLines = (result) => result.strayOverrides.length
387
407
  * всплывали бы только там, где и без них уже красно.
388
408
  */
389
409
  const warnings = (result) => [
410
+ ...holeWarningLines(result),
390
411
  ...brokenLines(result),
391
412
  ...idleLines(result),
392
413
  ...namedCutLines(result),
@@ -396,7 +417,6 @@ const warnings = (result) => [
396
417
  ...strayLines(result),
397
418
  ];
398
419
  const describe = (result) => [
399
- ...holes(result),
400
420
  ...gapLines(result),
401
421
  ...unboundLines(result),
402
422
  ...driftedLines(result),
@@ -570,6 +590,24 @@ function refusalBeforeSync(env, config) {
570
590
  }
571
591
  return null;
572
592
  }
593
+ /**
594
+ * Надстройки, чья статья в новой редакции уже есть.
595
+ *
596
+ * Пометка без читателя ничего не меняет: тот, кто ставит новую версию, видит число разложенных
597
+ * файлов и не видит, что часть надстроек стала лишней. Раскладка их называет, снимает человек:
598
+ * пометка держит одну статью, а в раздел могли дописать и другое.
599
+ */
600
+ function staleOverrideLines(root, assetsDir) {
601
+ const stale = staleOverrides(root, assetsDir);
602
+ if (!stale.length) {
603
+ return [];
604
+ }
605
+ return [
606
+ `надстройки, чья статья в пакете уже есть: ${stale.length}`,
607
+ ...stale.map((mark) => ` ${mark.file} · раздел «${mark.heading}» · отправлено ${mark.day}`),
608
+ ' — раздел снимается, и дерево возвращается к пакетной формулировке',
609
+ ];
610
+ }
573
611
  /** Ответ `sync --check`: расхождения считаются, на диск не пишется ничего. */
574
612
  function syncCheck(config, root, version, assetsDir) {
575
613
  {
@@ -587,7 +625,10 @@ function syncCheck(config, root, version, assetsDir) {
587
625
  // Гард, подписанный не на то, что объявляет, идёт в счёт по той же причине и с большим
588
626
  // основанием: неподключённый хотя бы не притворяется — этот выглядит работающим, и ветка
589
627
  // его тела, ради которой всё писалось, не исполняется ни разу.
590
- const count = result.missing.size + result.gaps.length + pending.length + empty.length + result.unbound.length + result.drifted.length;
628
+ // Незаполненная дырка в счёт не входит: она говорит о том, чего дерево ещё не описало о
629
+ // себе, а не о расхождении разложенного с редакцией. Она печатается предупреждением —
630
+ // и на сошедшемся дереве тоже.
631
+ const count = result.gaps.length + pending.length + empty.length + result.unbound.length + result.drifted.length;
591
632
  if (!count) {
592
633
  return { code: 0, lines: [`sync --check: разложенное сходится с пакетом v${version}`, ...warnings(result)] };
593
634
  }
@@ -646,6 +687,7 @@ export function sync(env, check) {
646
687
  ...boundLines(result),
647
688
  ...(result.bound?.unreadable === false ? [] : unboundLines(result)),
648
689
  ...driftedLines(result),
690
+ ...staleOverrideLines(root, assetsDir),
649
691
  ...debtLines(config, root, assetsDir),
650
692
  ...warnings(result),
651
693
  ],
@@ -787,6 +829,24 @@ function offFileLines(summary) {
787
829
  }
788
830
  return [` не на правке файла: ${summary.denialsOffFile} из ${total} — ${Math.round((summary.denialsOffFile / total) * 100)}%`];
789
831
  }
832
+ /**
833
+ * Исходы гейта пуша. Молчит, когда гейт не отработал ни разу за отрезок.
834
+ *
835
+ * Вынесено из сводки отдельной функцией не ради имени: та собирает строки одним выражением, и
836
+ * каждая новая развилка в нём растит её сложность, за которой следит линтер.
837
+ */
838
+ function pushGateOutcomeLines(summary) {
839
+ if (!summary.pushGate.length) {
840
+ return [];
841
+ }
842
+ const total = summary.pushGate.reduce((found, entry) => found + entry.count, 0);
843
+ return [
844
+ '',
845
+ `гейт пуша прогонял набор: ${total}`,
846
+ ...countLines(summary.pushGate),
847
+ ' — green зелёный набор, red красный, no-checks проверок в дереве не нашлось',
848
+ ];
849
+ }
790
850
  /** Сводка строками: загруженное, незагруженное, отбивки гейта и отказы гардов. */
791
851
  function statsLines(summary, swept, days, version, laidOut) {
792
852
  return [
@@ -834,6 +894,7 @@ function statsLines(summary, swept, days, version, laidOut) {
834
894
  ...countLines(summary.guards),
835
895
  ]
836
896
  : []),
897
+ ...pushGateOutcomeLines(summary),
837
898
  ...(summary.silentGuards.length
838
899
  ? [
839
900
  '',