@rt-tools/agent-kit 0.22.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 (101) hide show
  1. package/README.md +8 -2
  2. package/assets/checks/board-long-work.github.mjs +101 -0
  3. package/assets/checks/board-runs.github.mjs +34 -0
  4. package/assets/checks/board.github.mjs +1 -1
  5. package/assets/checks/check-board.github.mjs +30 -2
  6. package/assets/checks/check-doc-paths.mjs +24 -5
  7. package/assets/checks/check-file-size.mjs +8 -2
  8. package/assets/checks/check-prose-style.mjs +10 -1
  9. package/assets/checks/check-reuse.mjs +4 -1
  10. package/assets/checks/check-schema-drift.mjs +65 -6
  11. package/assets/checks/rt-kit-checks.config.mjs +13 -0
  12. package/assets/checks/signals.mjs +41 -1
  13. package/assets/commands/next-session.md +16 -5
  14. package/assets/defaults/gate-map.sh +13 -0
  15. package/assets/defaults/project.sh +26 -0
  16. package/assets/defaults/shell.sh +18 -3
  17. package/assets/hooks/browser-guard-device-id.sh +42 -12
  18. package/assets/hooks/browser-guard-no-asking.sh +5 -1
  19. package/assets/hooks/dispatch.sh +40 -9
  20. package/assets/hooks/docs-guard.sh +10 -0
  21. package/assets/hooks/exam-guard.sh +66 -16
  22. package/assets/hooks/git-guard-delivery-draft.sh +78 -0
  23. package/assets/hooks/git-guard-delivery.sh +64 -122
  24. package/assets/hooks/git-guard-main.sh +39 -4
  25. package/assets/hooks/git-guard-push-tests.sh +71 -3
  26. package/assets/hooks/glossary-load.sh +23 -2
  27. package/assets/hooks/grill-gate.sh +62 -0
  28. package/assets/hooks/hook-input.sh +17 -6
  29. package/assets/hooks/rule-source-guard.sh +11 -0
  30. package/assets/hooks/stand-login-guard.sh +101 -0
  31. package/assets/hooks/write-targets.sh +37 -4
  32. package/assets/laws/autonomous-work.md +30 -0
  33. package/assets/laws/project-documentation.md +8 -0
  34. package/assets/laws/verifiability.md +12 -2
  35. package/assets/laws/work-conduct.md +59 -65
  36. package/assets/patterns/autonomous-work-run.md +105 -0
  37. package/assets/patterns/browser-verification-measure.md +41 -1
  38. package/assets/patterns/browser-verification-stand.md +57 -16
  39. package/assets/patterns/doc-style-human.md +75 -0
  40. package/assets/patterns/doc-style-write.md +16 -0
  41. package/assets/patterns/git-workflow-commit.azure.md +12 -0
  42. package/assets/patterns/git-workflow-commit.github.md +16 -3
  43. package/assets/patterns/git-workflow-commit.gitlab.md +12 -0
  44. package/assets/patterns/git-workflow-merge.md +8 -0
  45. package/assets/patterns/git-workflow-pr-ready.md +93 -0
  46. package/assets/patterns/git-workflow-pr.azure.md +1 -1
  47. package/assets/patterns/git-workflow-pr.github.md +1 -1
  48. package/assets/patterns/git-workflow-pr.gitlab.md +1 -1
  49. package/assets/patterns/task-flow-start.md +48 -48
  50. package/assets/patterns/testing-e2e.md +18 -8
  51. package/assets/patterns/ts-procedure.md +3 -2
  52. package/assets/pitfalls/task-flow.md +40 -40
  53. package/assets/rules/autonomous-work.md +92 -0
  54. package/assets/rules/browser-verification.md +35 -3
  55. package/assets/rules/deploy-flow.azure.md +7 -0
  56. package/assets/rules/deploy-flow.github.md +7 -0
  57. package/assets/rules/deploy-flow.gitlab.md +7 -0
  58. package/assets/rules/doc-style.md +54 -0
  59. package/assets/rules/git-workflow.azure.md +8 -0
  60. package/assets/rules/git-workflow.github.md +59 -63
  61. package/assets/rules/git-workflow.gitlab.md +8 -0
  62. package/assets/rules/reuse-first.md +25 -5
  63. package/assets/rules/styling-bem.md +8 -1
  64. package/assets/rules/task-flow.md +108 -109
  65. package/assets/rules/testing.md +21 -0
  66. package/assets/skills/agent-kit.md +72 -82
  67. package/lib/commands.d.ts.map +1 -1
  68. package/lib/commands.js +69 -2
  69. package/lib/commands.js.map +1 -1
  70. package/lib/enroll.d.ts.map +1 -1
  71. package/lib/enroll.js +1 -1
  72. package/lib/enroll.js.map +1 -1
  73. package/lib/observations.d.ts +10 -1
  74. package/lib/observations.d.ts.map +1 -1
  75. package/lib/observations.js +1 -0
  76. package/lib/observations.js.map +1 -1
  77. package/lib/override-marks.d.ts +24 -0
  78. package/lib/override-marks.d.ts.map +1 -0
  79. package/lib/override-marks.js +98 -0
  80. package/lib/override-marks.js.map +1 -0
  81. package/lib/push-gate.d.ts +14 -0
  82. package/lib/push-gate.d.ts.map +1 -0
  83. package/lib/push-gate.js +93 -0
  84. package/lib/push-gate.js.map +1 -0
  85. package/lib/shipment.d.ts.map +1 -1
  86. package/lib/shipment.js +1 -1
  87. package/lib/shipment.js.map +1 -1
  88. package/package.json +1 -1
  89. package/rt-tools-agent-kit-0.24.0.tgz +0 -0
  90. package/assets/laws/application/access.md +0 -34
  91. package/assets/laws/application/locales.md +0 -33
  92. package/assets/laws/application/search-visibility.md +0 -24
  93. package/assets/patterns/permissions-procedure.md +0 -71
  94. package/assets/patterns/seo-page.md +0 -104
  95. package/assets/patterns/seo-verify.md +0 -83
  96. package/assets/patterns/translations-content.md +0 -107
  97. package/assets/patterns/translations-key.md +0 -64
  98. package/assets/rules/permissions.md +0 -116
  99. package/assets/rules/seo.md +0 -139
  100. package/assets/rules/translations.md +0 -96
  101. package/rt-tools-agent-kit-0.22.0.tgz +0 -0
@@ -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,60 +177,65 @@ 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
 
231
- 1. `init`, затем `skip` на всё, что дерево держит само. Пустая раскладка — законное начало.
232
- 2. Снимок того, что говорят проверки дерева, до единой правки. Он и есть мерило.
228
+ 1. `init`, затем `skip` на всё, что дерево держит само; пустая раскладка — законное начало.
229
+ 2. Снимок того, что говорят проверки дерева, до единой правки: он и есть мерило.
233
230
  3. Ресурс за ресурсом: пакетную редакцию довести до здешней, предметность вынести в
234
231
  надстройку, снять отказ, разложить, прогнать сценарии и сверить снимок.
235
232
  4. Разложенное поверх своего пакет не пишет: файл без шапки для него чужой. Отдаётся он
236
- командой `adopt` — прежнее содержимое ложится рядом с пометкой `.before-rt-kit`, и снять его
237
- потом решает владелец.
238
- 5. Свои сценарии отданного файла переписываются под пакетное поведение либо снимаются. Чинить
239
- пакетную редакцию на месте нельзя: правка разложенной копии живёт до следующей раскладки, а
240
- её адрес источник пакета или надстройка дерева. Сценарий, ждущий поведения снятого файла,
241
- краснеет и после верной отдачи: он проверяет то, чего в дереве больше нет.
233
+ командой `adopt` — прежнее содержимое ложится рядом с пометкой `.before-rt-kit`.
234
+ 5. Ресурс, у которого здешняя редакция богаче пакетной по существу, в раскладку не берётся.
235
+ Признак статья, которой в пакетной редакции нет и не может быть: она выводится из предмета
236
+ дерева. Он уходит в `skip`, а наверх едет предложение снять его из пакета.
237
+ 6. Свои сценарии отданного файла переписываются под пакетное поведение либо снимаются: чинить
238
+ пакетную редакцию на месте нельзя, её адрес источник пакета или надстройка.
242
239
 
243
240
  ## Свойства дерева
244
241
 
@@ -272,27 +269,20 @@ npx agent-kit adopt [файлы] # отдать пакету свой файл,
272
269
 
273
270
  ## Ловушки раскладки
274
271
 
275
- - **Запись файла командой оболочки судится по всем путям, названным в её теле.** Гейт вынимает
276
- пути из текста команды, а тело документа читает целиком, как только в команде встречается имя
277
- интерпретатора, и строка запуска первой строкой записываемого файла возвращает его туда сама.
278
- Строка импорта разложенного модуля требует тогда правило пакетного слоя наравне с правилом
279
- самого файла, а требуется за раз одно: два отказа подряд, и каждый уносит уже написанное тело.
280
- Инструмент правки судится одним своим путём и переписывать тело не заставляет; перенаправление
281
- оболочки остаётся для того, что файлом дерева не станет.
282
- - **Своё, стоящее рядом с разложенным, повторяет его механику молча.** Проверка, гард и утилита
283
- дерева лежат в тех же каталогах, что и пакетные, а общий разбор списка известного, корни
284
- исходников, список пропускаемых каталогов и снимок долга приезжают модулем настройки проверок.
285
- Второе такое же заводится в своей проверке без единого сигнала: имена разные, форма разная, и
286
- повтора не видит ни сверка раскладки файл не разложен, ни проверка повторов, которая ищет
287
- совпадение текста. Признак один, и он читается, а не ищется: до того как в своей проверке
288
- заводится разбор списка, чтение настройки или сравнение с накопленным, смотрят, что
289
- экспортирует модуль настройки проверок и чем живут соседние проверки.
272
+ - **Словарь такой же разложенный ресурс, как правило.** Хук запуска кладёт его в контекст
273
+ целиком, до первой реплики, и оттого он выглядит обычным документом дерева; шапка у него есть,
274
+ но читается служебной строкой. Новое слово идёт в надстройку словаря, своим разделом.
275
+
276
+ - **Запись файла командой оболочки проверяется по всем путям, названным в её теле.** Гейт
277
+ вынимает пути из текста команды и читает тело документа целиком, если в команде есть имя
278
+ интерпретатора; строка импорта разложенного модуля тогда требует второе правило, а требуется
279
+ за раз одно два отказа подряд, и каждый теряет написанное тело. Инструмент правки
280
+ проверяется одним своим путём; перенаправление оболочки для того, что файлом дерева не станет.
281
+ - **Своё, стоящее рядом с разложенным, повторяет его механику молча.** Разбор списка известного,
282
+ корни исходников и снимок долга даёт модуль настройки проверок; второй такой же разбор в своей
283
+ проверке не видит ни сверка раскладки, ни проверка повторов. Перед тем как завести своё, смотрят,
284
+ что экспортирует модуль настройки проверок.
290
285
  - **Правило, загруженное инструментом, бывает показано не целиком, и обрыв ничем не помечен.**
291
- Длинный файл приезжает в контекст обрезанным по строке, а снаружи это выглядит концом: показанное
292
- кончается осмысленным пунктом, и число разделов с оглавлением никто не сверяет. Бьёт обрыв ровно
293
- по хвосту, а хвост то место, где дерево отменяет умолчания пакета: разделы надстройки сливаются
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;AAsB7C,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,CA6E3D;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,8 @@ 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';
18
+ import { pushGateLines } from './push-gate.js';
17
19
  import { laidOutSkills, treeSnapshot } from './snapshot.js';
18
20
  import { mergedBody, pendingOf, planSync, runSync } from './sync.js';
19
21
  import { thresholdLines } from './thresholds.js';
@@ -185,6 +187,25 @@ const holes = (result) => [...result.missing].map(([asset, names]) => {
185
187
  const written = names.map(holeOf).join(', ');
186
188
  return ` ${asset}: нет значений для ${written}`;
187
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
+ : [];
188
209
  const unfilled = (result) => result.companions.filter(isUnfilled);
189
210
  /**
190
211
  * Строка про компаньон, которому нечего сказать.
@@ -386,6 +407,7 @@ const strayLines = (result) => result.strayOverrides.length
386
407
  * всплывали бы только там, где и без них уже красно.
387
408
  */
388
409
  const warnings = (result) => [
410
+ ...holeWarningLines(result),
389
411
  ...brokenLines(result),
390
412
  ...idleLines(result),
391
413
  ...namedCutLines(result),
@@ -395,7 +417,6 @@ const warnings = (result) => [
395
417
  ...strayLines(result),
396
418
  ];
397
419
  const describe = (result) => [
398
- ...holes(result),
399
420
  ...gapLines(result),
400
421
  ...unboundLines(result),
401
422
  ...driftedLines(result),
@@ -569,6 +590,24 @@ function refusalBeforeSync(env, config) {
569
590
  }
570
591
  return null;
571
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
+ }
572
611
  /** Ответ `sync --check`: расхождения считаются, на диск не пишется ничего. */
573
612
  function syncCheck(config, root, version, assetsDir) {
574
613
  {
@@ -586,7 +625,10 @@ function syncCheck(config, root, version, assetsDir) {
586
625
  // Гард, подписанный не на то, что объявляет, идёт в счёт по той же причине и с большим
587
626
  // основанием: неподключённый хотя бы не притворяется — этот выглядит работающим, и ветка
588
627
  // его тела, ради которой всё писалось, не исполняется ни разу.
589
- 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;
590
632
  if (!count) {
591
633
  return { code: 0, lines: [`sync --check: разложенное сходится с пакетом v${version}`, ...warnings(result)] };
592
634
  }
@@ -645,6 +687,7 @@ export function sync(env, check) {
645
687
  ...boundLines(result),
646
688
  ...(result.bound?.unreadable === false ? [] : unboundLines(result)),
647
689
  ...driftedLines(result),
690
+ ...staleOverrideLines(root, assetsDir),
648
691
  ...debtLines(config, root, assetsDir),
649
692
  ...warnings(result),
650
693
  ],
@@ -786,6 +829,24 @@ function offFileLines(summary) {
786
829
  }
787
830
  return [` не на правке файла: ${summary.denialsOffFile} из ${total} — ${Math.round((summary.denialsOffFile / total) * 100)}%`];
788
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
+ }
789
850
  /** Сводка строками: загруженное, незагруженное, отбивки гейта и отказы гардов. */
790
851
  function statsLines(summary, swept, days, version, laidOut) {
791
852
  return [
@@ -833,6 +894,7 @@ function statsLines(summary, swept, days, version, laidOut) {
833
894
  ...countLines(summary.guards),
834
895
  ]
835
896
  : []),
897
+ ...pushGateOutcomeLines(summary),
836
898
  ...(summary.silentGuards.length
837
899
  ? [
838
900
  '',
@@ -968,6 +1030,11 @@ export function doctor(env) {
968
1030
  return ` снят каскадом: ${one.id} — вслед за ${one.parent}${root}`;
969
1031
  }),
970
1032
  ...profileLines(root, assetsDir, config),
1033
+ // Набор перед пушем — итоговый, а не пересказ умолчания: собирается он из двух файлов, и
1034
+ // прочитать сборку было нечем. Дерево, пишущее надстройку, видит здесь умолчание и не
1035
+ // дописывает повтор, а снятое надстройкой видно на разборе ветки, а не только тому, кто
1036
+ // его снял.
1037
+ ...pushGateLines(root, config.layout.defaults ?? DEFAULT_LAYOUT.defaults),
971
1038
  ...localValueLines(root, assetsDir, config),
972
1039
  ...replacedLines(config, assetsDir, root),
973
1040
  ...thresholdLines(root),