@rt-tools/agent-kit 0.16.1 → 0.18.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 (136) hide show
  1. package/assets/checks/board-epics.github.mjs +123 -0
  2. package/assets/checks/board-gh.github.mjs +121 -0
  3. package/assets/checks/board-paths.github.mjs +88 -0
  4. package/assets/checks/board-runs.github.mjs +8 -0
  5. package/assets/checks/board-titles.github.mjs +66 -0
  6. package/assets/checks/board.github.mjs +77 -73
  7. package/assets/checks/check-board.github.mjs +56 -7
  8. package/assets/checks/check-file-size.mjs +10 -2
  9. package/assets/checks/check-glossary.mjs +170 -0
  10. package/assets/checks/check-hook-scope.mjs +126 -0
  11. package/assets/checks/check-profile-drift.mjs +195 -0
  12. package/assets/checks/check-push-gate.mjs +59 -1
  13. package/assets/checks/check-schema-drift.mjs +12 -5
  14. package/assets/checks/check-specs.mjs +1 -1
  15. package/assets/checks/rt-kit-checks.config.mjs +13 -0
  16. package/assets/checks/spec-anchors.mjs +2 -2
  17. package/assets/checks/spec-contract.mjs +9 -0
  18. package/assets/defaults/gate-map.sh +13 -4
  19. package/assets/defaults/project.sh +31 -108
  20. package/assets/defaults/shell.sh +139 -0
  21. package/assets/docs/GLOSSARY.md +1 -1
  22. package/assets/hooks/browser-device-id.sh +20 -4
  23. package/assets/hooks/browser-guard-device-id.sh +5 -2
  24. package/assets/hooks/browser-guard-no-other-drivers.sh +41 -2
  25. package/assets/hooks/claim-guard.sh +22 -1
  26. package/assets/hooks/docs-guard.sh +1 -1
  27. package/assets/hooks/exam-guard.sh +85 -12
  28. package/assets/hooks/git-guard-delivery-conflict.sh +85 -0
  29. package/assets/hooks/git-guard-delivery-folder.sh +19 -0
  30. package/assets/hooks/git-guard-delivery-signature.sh +14 -5
  31. package/assets/hooks/git-guard-delivery.sh +54 -2
  32. package/assets/hooks/git-guard-push-tests.sh +21 -1
  33. package/assets/hooks/grill-gate-ask.sh +25 -0
  34. package/assets/hooks/grill-gate.sh +75 -11
  35. package/assets/hooks/lint-after-edit.sh +44 -16
  36. package/assets/hooks/proposal-guard.sh +11 -4
  37. package/assets/hooks/rule-source-guard.sh +8 -13
  38. package/assets/hooks/skill-gate-layers.sh +7 -0
  39. package/assets/hooks/skill-gate.sh +29 -0
  40. package/assets/hooks/task-context-load.sh +32 -0
  41. package/assets/hooks/task-flow-context.sh +194 -0
  42. package/assets/hooks/task-flow-draft-guard.sh +109 -0
  43. package/assets/hooks/task-flow-guard.sh +27 -159
  44. package/assets/hooks/turn-exit-guard.sh +53 -88
  45. package/assets/hooks/waiting-turn-guard.sh +65 -2
  46. package/assets/hooks/window-fill-guard.sh +5 -1
  47. package/assets/hooks/work-start-guard.sh +166 -0
  48. package/assets/hooks/write-targets.sh +24 -0
  49. package/assets/laws/delivery.md +19 -0
  50. package/assets/laws/frontend-application.md +4 -0
  51. package/assets/laws/verifiability.md +44 -0
  52. package/assets/laws/work-conduct.md +15 -0
  53. package/assets/patterns/browser-verification-measure.md +3 -1
  54. package/assets/patterns/browser-verification-stand.md +17 -4
  55. package/assets/patterns/doc-style-write.md +62 -2
  56. package/assets/patterns/git-workflow-commit.github.md +33 -5
  57. package/assets/patterns/git-workflow-docker.md +22 -0
  58. package/assets/patterns/git-workflow-freshness.md +87 -0
  59. package/assets/patterns/git-workflow-merge.md +41 -0
  60. package/assets/patterns/git-workflow-migration.md +11 -0
  61. package/assets/patterns/git-workflow-pr.github.md +12 -1
  62. package/assets/patterns/git-workflow-restart.md +18 -0
  63. package/assets/patterns/git-workflow-secrets.md +14 -0
  64. package/assets/patterns/git-workflow-stack.md +93 -1
  65. package/assets/patterns/lib-layers-move.md +4 -0
  66. package/assets/patterns/spec-driven-domain.md +47 -2
  67. package/assets/patterns/spec-driven-rule.md +16 -4
  68. package/assets/patterns/spec-driven-sweep.md +57 -0
  69. package/assets/patterns/status-report-table.github.md +1 -1
  70. package/assets/patterns/task-flow-archive.md +58 -16
  71. package/assets/patterns/task-flow-close.md +106 -23
  72. package/assets/patterns/task-flow-handoff.md +14 -2
  73. package/assets/patterns/task-flow-resume.md +35 -8
  74. package/assets/patterns/task-flow-start.md +60 -22
  75. package/assets/patterns/testing-e2e.md +23 -0
  76. package/assets/patterns/turn-entry-map.md +1 -1
  77. package/assets/pitfalls/agent-kit.md +71 -3
  78. package/assets/pitfalls/doc-style.md +15 -0
  79. package/assets/pitfalls/git-workflow.github.md +88 -0
  80. package/assets/pitfalls/spec-driven.md +22 -0
  81. package/assets/pitfalls/task-flow.md +113 -0
  82. package/assets/pitfalls/testing.md +6 -0
  83. package/assets/pitfalls/turn-conduct.md +49 -0
  84. package/assets/rules/browser-verification.md +58 -0
  85. package/assets/rules/deploy-flow.azure.md +8 -0
  86. package/assets/rules/deploy-flow.github.md +27 -0
  87. package/assets/rules/deploy-flow.gitlab.md +8 -0
  88. package/assets/rules/doc-style.md +20 -0
  89. package/assets/rules/git-workflow.azure.md +22 -2
  90. package/assets/rules/git-workflow.github.md +127 -118
  91. package/assets/rules/git-workflow.gitlab.md +17 -4
  92. package/assets/rules/lists.md +5 -0
  93. package/assets/rules/observability.needs-app.md +4 -0
  94. package/assets/rules/reuse-first.md +14 -0
  95. package/assets/rules/shared-code.md +5 -0
  96. package/assets/rules/spec-driven.md +33 -15
  97. package/assets/rules/task-flow.md +132 -126
  98. package/assets/rules/testing.md +41 -2
  99. package/assets/rules/turn-conduct.md +73 -57
  100. package/assets/rules/turn-entry.md +6 -0
  101. package/assets/samples/tasks/_template/grill.md +5 -0
  102. package/assets/samples/tasks/_template/plan.md +3 -0
  103. package/assets/skills/agent-kit.md +108 -76
  104. package/assets/templates/postmortem.md +5 -1
  105. package/bin/agent-kit.d.ts.map +1 -1
  106. package/bin/agent-kit.js +30 -6
  107. package/bin/agent-kit.js.map +1 -1
  108. package/lib/catalog.d.ts.map +1 -1
  109. package/lib/catalog.js +2 -1
  110. package/lib/catalog.js.map +1 -1
  111. package/lib/commands.d.ts.map +1 -1
  112. package/lib/commands.js +96 -7
  113. package/lib/commands.js.map +1 -1
  114. package/lib/hooks-map.d.ts +26 -0
  115. package/lib/hooks-map.d.ts.map +1 -1
  116. package/lib/hooks-map.js +58 -2
  117. package/lib/hooks-map.js.map +1 -1
  118. package/lib/sections.d.ts +6 -0
  119. package/lib/sections.d.ts.map +1 -1
  120. package/lib/sections.js +19 -0
  121. package/lib/sections.js.map +1 -1
  122. package/lib/shipment.d.ts +2 -0
  123. package/lib/shipment.d.ts.map +1 -1
  124. package/lib/shipment.fixture.d.ts +5 -0
  125. package/lib/shipment.fixture.d.ts.map +1 -1
  126. package/lib/shipment.fixture.js +7 -0
  127. package/lib/shipment.fixture.js.map +1 -1
  128. package/lib/shipment.js +13 -1
  129. package/lib/shipment.js.map +1 -1
  130. package/lib/sync.d.ts +35 -3
  131. package/lib/sync.d.ts.map +1 -1
  132. package/lib/sync.js +59 -8
  133. package/lib/sync.js.map +1 -1
  134. package/package.json +1 -1
  135. package/rt-tools-agent-kit-0.18.0.tgz +0 -0
  136. package/rt-tools-agent-kit-0.16.1.tgz +0 -0
@@ -12,14 +12,22 @@ description: Паттерн правила task-flow. Брать при дове
12
12
 
13
13
  ## Когда брать
14
14
 
15
- - Этапы замысла закрыты, набор гейта прогнан целиком.
15
+ - Этапы замысла закрыты.
16
16
  - `npm run check:specs` перечислил договорённость в разделе «Пора вливать».
17
+ - Спек меряется длиной сразу после вливания: выросший делится тем же коммитом.
17
18
  - Тексты домена приводятся к тому, что работа сделала.
19
+ - Набор гейта прогнан целиком — после вливания и приведения текстов, а не до них.
18
20
  - Папка задачи разобрана, и заявка открывается черновиком.
19
21
  - Прогон на вершине зелёный, и с заявки снимается черновик.
20
22
 
21
23
  Разбор самой папки сюда не относится — это паттерн `task-flow-archive`. Он стоит между
22
- приведением текстов и открытием заявки: заявка открывается уже за убранной работой.
24
+ прогоном набора и открытием заявки: заявка открывается уже за убранной работой.
25
+
26
+ **Прогон стоит после вливания договорённости и приведения текстов, а не перед ними.** Оба этих
27
+ шага стоят минуты, а прогон — окно захода: заход, потративший его на прогон, упирался в порог
28
+ заполнения на четырёх строках привязки, и дописать их было уже нечем. Второй довод сильнее
29
+ первого — прогон, идущий после вливания, проверяет и само вливание; идущий до него, он смотрит
30
+ то состояние дерева, которое в главную ветку не поедет.
23
31
 
24
32
  ## Состояние `этапы-кончились`: договорённость вливается в спек домена
25
33
 
@@ -30,11 +38,19 @@ description: Паттерн правила task-flow. Брать при дове
30
38
  npm run check:specs # раздел «Пора вливать» называет готовые директории
31
39
  ```
32
40
 
41
+ **Спек меряется длиной тем же ходом.** Вливание — известное движение, растящее спек: одно
42
+ довело его до 572 строк при пределе 500, и узнал об этом исполнитель отказом гарда пуша, то
43
+ есть после коммита. Выросший делится на поддомены здесь же, а не на пуше.
44
+
33
45
  Порядок переезда:
34
46
 
35
47
  - правила из `proposed/<фича>/spec.md` дописываются в `spec.md` домена, в его разделы;
36
48
  - сценарии переезжают в `scenarios.md` домена **с прежними номерами**: на них ссылаются
37
49
  заголовки тестов, и пересчёт рвёт сверку;
50
+ - сценарии, у которых работа переписала обещание, правятся на месте: номер прежний, текст
51
+ новый, заголовок теста правится тем же коммитом. Работа, снимающая приём, переписывает уже
52
+ записанное обещание чаще, чем заводит новое, а список, перечисляющий одну допись, эту правку
53
+ не называет вовсе;
38
54
  - привязки из `proposed/<фича>/implementation.md` дописываются в `implementation.md` домена
39
55
  и проставляются на код, который теперь есть;
40
56
  - законы, объявленные фичей в шапке, дописываются в шапку спека домена;
@@ -103,11 +119,60 @@ grep -rn -A3 "Чего из закона здесь нет" <каталог пр
103
119
  работа ждёт владельца, а не машину, и заход на этом не кончается: следующая задача берётся тем
104
120
  же движением, паттерн `task-flow-resume`.
105
121
 
122
+ **Готовность меряется рассказанностью, а не пройденностью.** Перечень того, что сделано к
123
+ открытию, читается как список обязательных проверок, и границы у него не видно. Она есть:
124
+ проверка, которую исполнитель не может пройти по причине вне работы — отбитое разрешение,
125
+ недоступная среда, ключ у человека, — готовность не отменяет. Она попадает в «Не гонялось» и в
126
+ «Оставшийся шаг», названная вместе с причиной; умолчание о ней читается как пройденная.
127
+
106
128
  Состояния на диске уже нет — ход работы уехал вместе с папкой. Это цена того, что уборка стоит
107
129
  до заявки: хвост из четырёх шагов — открыть заявку, дождаться прогона, снять черновик, попросить
108
130
  влить — держится этим паттерном, а не строкой в файле. Гард признаёт работу отданной по истории
109
131
  ветки: папка, снятая её коммитом, и есть признак.
110
132
 
133
+ ### Раздел об оставшемся шаге пишется в теле заявки, а не дописывается потом
134
+
135
+ Он стоит там с минуты открытия. Сказанного вслух мало, и одним этим требование не держится:
136
+ реплика живёт до следующей реплики, а решение о слиянии принимается на странице заявки — там
137
+ переписки нет вовсе. Владелец вливает, как только видит зелёное, и заявка, открытая без раздела,
138
+ уезжает в главную ветку раньше, чем раздел успевают дописать: так папка задачи однажды и уехала
139
+ неразобранной, пока шёл прогон. Раздел стоит последним и говорит ровно одно: осталось ли что-то
140
+ до слияния.
141
+
142
+ ```markdown
143
+ ## Оставшийся шаг
144
+
145
+ Папка задачи разобрана коммитом `<sha>` — за работой убрано. Осталось дождаться прогона и снять
146
+ черновик; до этого кнопка слияния заблокирована хостингом.
147
+ ```
148
+
149
+ Черновик снят — раздел переписывается тем же вызовом, которым правится тело:
150
+
151
+ ```markdown
152
+ ## Оставшийся шаг
153
+
154
+ Не осталось: прогон зелёный, черновик снят. Можно вливать.
155
+ ```
156
+
157
+ Заголовок раздела и слова обоих образцов пишутся языком заявки, а не языком паттерна. Образцы
158
+ набраны тем языком, которым написан сам паттерн, и переносятся целиком — порядок мыслей,
159
+ формулировки и заголовок, заголовок последним: он выглядит частью формы, а не частью текста.
160
+ То же верно и для двух сообщений владельцу ниже: они образцы того, **что** сказано, а не того,
161
+ какими словами.
162
+
163
+ Пустым раздел не оставляется и не удаляется вовсе: отсутствие раздела и «шагов не осталось»
164
+ читаются одинаково, а значат разное. Образец тела заявки целиком — в паттерне заведения коммита
165
+ и заявки, если дерево его разложило.
166
+
167
+ Держит это гард поставки, а не память пишущего: он читает тело прямо из команды открытия —
168
+ доводом оно передано или файлом — и отбивает вызов вместе с остальным несошедшимся. Образец
169
+ заголовка при этом называет дерево, потому что заголовок пишется языком заявки, а пакет чужих
170
+ слов не знает; не названный, раздел не судится вовсе. Сверка очереди работ тела по-прежнему не
171
+ читает: промах ловится в минуту открытия, то есть там, где он ещё исправим одним вызовом.
172
+
173
+ Разница между разделом и сказанным вслух одна, и она вся: реплику владелец прочитает, только
174
+ если вернётся в переписку, а раздел он видит там, куда смотрит, нажимая кнопку.
175
+
111
176
  ### Два сообщения владельцу, и между ними — прогон
112
177
 
113
178
  Оба обязательны, и порядок между ними один. Ни одно не заменяется другим: первое говорит, что
@@ -175,6 +240,12 @@ PR #<номер> готов к слиянию: прогон зелёный, че
175
240
  читаются одинаково, а значат разное. Образец тела заявки целиком — в паттерне заведения коммита
176
241
  и заявки, если дерево его разложило.
177
242
 
243
+ Открытая заявка перечитывается той записью, которая будет её вливать, а не той, что её открыла.
244
+ Ответ хостинга автору говорит лишь, что вызов прошёл: право на открытие и видимость открытого —
245
+ разные вещи, и вторая проверяется только со стороны читателя. Невидимая заявка ничем себя не
246
+ выдаёт — она есть в ответе своему автору, у неё стоят метки, а очередь разбора у владельца просто
247
+ пуста.
248
+
178
249
  Проверить это машиной нечем, и проверки не будет: тело заявки не читает ни одна сверка, а
179
250
  хостинг не спрашивает ни о чём, кроме заголовка. Требование держится тем же, чем и слова
180
251
  вслух, — тем, кто пишет тело. Разница между ними одна, и она вся: реплику владелец прочитает,
@@ -186,29 +257,41 @@ PR #<номер> готов к слиянию: прогон зелёный, че
186
257
  нет, и собирать папку заново не надо: гард хода работы пропускает правку по признаку из истории
187
258
  ветки. Что именно чинится, берётся из замечания, а не из замысла.
188
259
 
260
+ Главная ветка, влитая ради того, чтобы что-то посмотреть, — такая же правка, как влитая ради
261
+ работы, и уезжает тем же ходом. Слияние, оставшееся в рабочей копии, либо пушится тем же ходом,
262
+ либо не делается — иначе владелец видит прежнее состояние и решает по нему.
263
+
189
264
  **Следующее движение:** прогон зелёный и замечаний нет — черновик снимается, и владельцу
190
265
  говорится, что работа готова.
191
266
 
192
- ## Ловушки
193
-
194
- - **Тексты правятся до разбора папки.** Список того, что перечитывать, лежит в замысле, а
195
- разбор папки его удаляет. После разбора остаётся только память о том, что задевали.
196
- - **Утверждение правила снимается вместе со строкой привязки.** Связь идёт по тексту
197
- утверждения. Убрали утверждение и оставили строку в `implementation.md` сверка спеков
198
- краснеет; убрали строку и оставили утверждение тоже.
267
+ ## Частые промахи
268
+
269
+ - **Тексты правятся до разбора папки:** список того, что перечитывать, лежит в замысле, а разбор
270
+ папки его удаляет.
271
+ - **Запись раздела решений, повторяющая статью правила слово в слово, доводом при ней не
272
+ считается.** Правило приходит в контекст само, спектолько когда его открыли; пара расходится
273
+ молча. Такая запись уезжает целиком, даже если раздел пустеет; довод, в статье не сказанный,
274
+ дописывается в статью.
275
+ - **Тело заявки остаётся старше разбора папки.** Разбор — последний коммит ветки, и он делает
276
+ неправдой всё, что тело обещало сделать до слияния. Ревьювер читает список оставшегося как
277
+ оставшееся, поэтому тело правится тем же ходом.
278
+ - **Утверждение правила снимается вместе со строкой привязки.** Связь идёт по тексту: строка без
279
+ утверждения и утверждение без строки одинаково краснят сверку спеков.
199
280
  - **Раздел «Чего из закона здесь нет» читается глазами, греп тут не помогает.** Искать
200
- приходится не то слово, которое ждёшь: правило ссылалось на статью закона, которой в законе
201
- нет вовсе, и по слову из своей темы эта строка находилась — а неправда была в другом.
202
- - **Сказать «сверено», не открыв файл, нельзя.** Правило читается целиком. Устаревшее
203
- утверждение стоит в списке среди верных и ничем от них не отличается.
281
+ приходится не то слово, которое ждёшь: правило ссылалось на статью, которой в законе нет, и по
282
+ слову своей темы эта строка находилась — а неправда была в другом.
283
+ - **Сказать «сверено», не открыв файл, нельзя.** Правило читается целиком: устаревшее утверждение
284
+ стоит среди верных и ничем от них не отличается.
204
285
  - **Вливание после мержа не делается.** В главной ветке тогда лежит раздел «предложено, но не
205
- выкачено» с тем, что работает месяц, беззвучная ложь, тем убедительнее, чем старше.
206
- - **Номера сценариев при вливании не пересчитываются.** Идентификатор — ключ связи с тестами;
207
- сдвиг рвёт сверку у соседей, которых правка не касалась.
208
- - **«Что не входит» после вливания читается целиком, а не дописывается.** Договорённость несёт
209
- свои границы, и при вливании они ложатся рядом с границами домена: половина повторяет уже
210
- стоявшее другими словами, а строка «этого раздела ещё нет» становится ложью ровно той
211
- работой, которая её вливает. Сверка спеков в этот раздел не смотрит вовсе. Снимается
212
- дословный повтор и то, что работа сделала входящим.
213
- - **Правило без привязки в спек домена не въезжает.** Кода, который его исполняет, нет
214
- значит это намерение, и место ему в открытых вопросах домена, а не в правилах.
286
+ выкачено» с тем, что работает месяц: беззвучная ложь, тем убедительнее, чем старше.
287
+ - **Номера сценариев при вливании не пересчитываются.** Идентификатор — ключ связи с тестами, и
288
+ сдвиг рвёт сверку у соседей.
289
+ - **«Что не входит» после вливания читается целиком, а не дописывается.** Границы фичи ложатся
290
+ рядом с границами домена: половина повторяет стоявшее другими словами, а строка «этого раздела
291
+ ещё нет» становится ложью той работой, которая её вливает. Сверка спеков туда не смотрит.
292
+ - **Своя строка сверки очереди ищется по имени** по номеру задачи и имени ветки: сверка
293
+ отвечает про всё дерево, и на одном закрытии чужих папок было восемь при одной своей.
294
+ - **Пара «метка объёма и строка в замысле эпика» рвётся с двух сторон:** задача по следу закрытой
295
+ наследует метку без строки о заходах, а закрытый эпик уносит строку у всех, кто её несёт.
296
+ - **Правило без привязки в спек домена не въезжает.** Кода, который его исполняет, нет — значит
297
+ это намерение, и место ему в открытых вопросах домена.
@@ -89,6 +89,8 @@ mkdir -p <каталог передачи>
89
89
  ```markdown
90
90
  Работа: <КЛЮЧ>-<номер> «<название задачи>». Рабочее дерево — <полный путь>, ветка
91
91
  <КЛЮЧ>-<номер>-<slug> (заведена, в работе).
92
+ Заявка: #<номер>, открыта, ждёт разбора владельцем. Свежесть её основания здесь не записана
93
+ намеренно — она протухает; спрашивается она у хранилища первым делом нового захода.
92
94
 
93
95
  Ход работы и замысел придут на запуске сессии хуком — перечитывать их файлами не надо. Разбор
94
96
  просьбы владельца лежит в папке задачи и читается, когда непонятна причина решения.
@@ -128,7 +130,8 @@ mkdir -p <каталог передачи>
128
130
 
129
131
  Разделы фиксированы, и порядок у них тот же:
130
132
 
131
- 1. **Работа** — номер задачи, её название, рабочее дерево полным путём, ветка и её состояние.
133
+ 1. **Работа** — номер задачи, её название, рабочее дерево полным путём, ветка и её состояние; у
134
+ отданной работы — номер открытой заявки и то, чего она ждёт.
132
135
  2. **Где искать** — что придёт хуком само, а что читается по надобности.
133
136
  3. **Эпик** — таблица положения; у работы вне эпика раздела нет.
134
137
  4. **Сделано и следующий шаг** — одной строкой каждое; подробности уже в ходе работы.
@@ -142,14 +145,23 @@ mkdir -p <каталог передачи>
142
145
  заход одной вставкой. Пересказывать содержание передачи в ответе не надо: владелец её и так
143
146
  прочитает, а место на неё уже потрачено.
144
147
 
145
- ## Ловушки
148
+ ## Частые промахи
146
149
 
147
150
  - **Заход закрывается на втором пороге, а не начинает на нём новый этап.** Напоминание на
148
151
  первом — это уже сигнал выбирать точку, а не работать дальше, пока не отобьют.
149
152
  - **Передача пишется как пересказ переписки.** В неё идёт то, чего нет ни в ходе работы, ни в
150
153
  правилах: дерево, ветка, состояние стендов. Всё остальное следующий заход прочитает сам.
154
+ - **Утверждение о состоянии работы берётся в тот же ход, а не вспоминается.** Родитель задачи,
155
+ её колонка, открытая заявка, влитая ветка, поднятые стенды живут вне захода и меняются без
156
+ него, а передача читается первой и не оспаривается: заход исполняет её указание, а не проверяет
157
+ его. Правдоподобие подтверждением не считается — «ветка не влита, значит и родителя нет» это
158
+ вывод, а не замер. Спросить нечем — так и пишется вопросом: «родитель не проверен, проверить
159
+ перед заявкой».
151
160
  - **Состояние работы в передачу не переезжает.** Сделанное отмечается в ходе работы — одной
152
161
  записью; передача его пересказывает, но не заменяет и в дерево не коммитится.
162
+ - **В передачу записано состояние, которое живёт часами.** Отставание от главной ветки, ход
163
+ прогона и «проверки зелёные» новый заход читает как верное сегодня. В передачу идёт то, что не
164
+ меняется без участия исполнителя: дерево, ветка, номер заявки, что не закоммичено.
153
165
  - **Незакоммиченное не названо.** Работа живёт в дереве неделями, и строка «что лежит
154
166
  несохранённым и почему» — единственное, по чему это видно.
155
167
  - **Заход, кончившийся ничем, тоже пишет передачу.** «Пробовали так — не вышло, потому что» —
@@ -27,11 +27,21 @@ description: Паттерн правила task-flow. Брать при возв
27
27
  образца, а `progress.md` заполняется по тому, что видно в дереве и в истории ветки, а не по
28
28
  расспросам владельца.
29
29
 
30
+ Пришло «РАБОТА ЗАКРЫВАЕТСЯ» — папку разобрала сама ветка перед заявкой, и собирать её заново не
31
+ надо: состояние работы читается у заявки и в передаче захода. Понадобилась правка кода по
32
+ замечаниям разбора — папка восстанавливается на время правки, а разбор повторяется тем же
33
+ коммитом.
34
+
30
35
  ## Чего не делать
31
36
 
32
37
  - **Не спрашивать владельца о том, что записано.** Ради этого всё и заведено.
33
38
  - **Не начинать заново то, что отмечено сделанным.** Отметка стоит в ходе работы; сомнение в
34
39
  ней проверяется деревом — сборкой, тестами, чтением файла, — а не вопросом.
40
+ - **Не выводить записанное заново из кода.** Запрет на вопрос этого не покрывает: решение,
41
+ выведенное из кода и поданное находкой, обходится дороже лишнего вопроса — владельцу
42
+ предлагают принять заново то, что он уже принял, и список вариантов звучит убедительнее
43
+ записи, которой он не видит. Прежде чем выводить, ищут в разборе просьбы, в ходе работы и в
44
+ замысле.
35
45
  - **Не править замысел.** С ним сверяют результат; пересмотр идёт записью в ходе работы.
36
46
 
37
47
  ## Вход из передачи захода
@@ -134,19 +144,25 @@ git log --oneline origin/main..HEAD
134
144
  Берётся, а не выбирается: порядок назначен на планировании и лежит в замысле эпика. Выбор,
135
145
  предложенный владельцу при назначенном порядке, — просьба назначить его заново.
136
146
 
147
+ У работы вне эпика замысла с порядком нет, и следующая берётся из очереди работ — тем же
148
+ движением и с тем же запретом на выбор вслух: очередь спрашивается командой, а не памятью о том,
149
+ что заводил сам исполнитель. Пусто в очереди — это утверждение о дереве, и подтверждается оно
150
+ выводом команды.
151
+
137
152
  ```bash
138
153
  # что назначено следующим — читается в замысле эпика, а не спрашивается
139
154
  # состояние задач — в очереди работ: замысел о закрытом не знает
140
155
  ```
141
156
 
142
157
  Останавливает заход только предел заполнения окна — тогда идёт передача, паттерн
143
- `task-flow-handoff`. Эпик кончился заход закрывается тем же порядком, и владельцу называется,
144
- что кончился именно эпик, а не одна его задача.
158
+ `task-flow-handoff`. Кончившийся эпик поводом остановиться не бывает: работа берётся вне его
159
+ из очереди работ, — а владельцу тем же ходом называется, что кончился именно эпик, а не одна его
160
+ задача. Он называется вместе со взятой работой, а не вместо неё.
145
161
 
146
162
  **Следующее движение:** по следующей задаче делается действие — заведена задача, ветка или
147
163
  папка. Ход кончается после него, а не после слов о нём.
148
164
 
149
- ## Ловушки
165
+ ## Частые промахи
150
166
 
151
167
  - **Заход, кончившийся ничем, тоже записывается.** Иначе следующий пойдёт той же дорогой:
152
168
  «пробовали так — не вышло, потому что» стоит одной строки и экономит целый заход.
@@ -154,10 +170,21 @@ git log --oneline origin/main..HEAD
154
170
  несохранённым и почему» — единственное, по чему это видно, пока PR нет.
155
171
  - **Подтверждение — вывод команды или замер, а не пересказ.** «Проверил, работает» через
156
172
  заход неотличимо от «казалось, что работает».
157
- - **Число из передачи пересчитывается до того, как на нём что-то делят.** Передача описывает
158
- день, когда её писали, лежит вне дерева, и не читает её ни одна проверка. Оценка «работы
159
- вдвое больше предыдущей» при пересчёте на текущем коммите не подтвердилась: по числу
160
- утверждений объёмы оказались почти равны. Деление работы по чужой оценке делит не то, и
161
- владельцу называются свои числа.
173
+ - **Число из передачи и из «Где стоим» пересчитывается перед тем, как попасть в любой новый
174
+ текст.** Не только перед делением работы: перенесённое в разбор просьбы или в ход работы, оно
175
+ читается следующими заходами как замер и не проверяется больше никем. Передача описывает
176
+ день, когда её писали, лежит вне дерева, и не читает её ни одна проверка. Счёт, взятый
177
+ непересчитанным, разошёлся с деревом на восемь и нашёлся сценарием подсчёта, а не чтением; та
178
+ же цена у оценки «работы вдвое больше предыдущей» — на текущем коммите объёмы оказались почти
179
+ равны. Пересчёт стоит одной команды, и в текст едет своё число.
162
180
  - **Доэтапное отделяется от своего.** Красное, найденное по дороге и не этой работой
163
181
  сделанное, помечается таковым сразу: иначе следующий заход примет его за свою поломку.
182
+ - **Разбор, написанный этим заходом, требованием для него не становится.** Запись объясняет
183
+ механизм, а исполняется он тем же, чем исполнялось прежнее, — вниманием того, кто ведёт ход:
184
+ через один ход после записи механизм повторился в той же форме. Поэтому разбор кончается не
185
+ текстом, а тем, что из него вышло: правкой ресурса, гардом или предложением с адресом. Заход,
186
+ дописавший разбор и вернувшийся к работе прежним, платит за него дважды.
187
+ - **Число находок, написанное словом, устаревает к следующему абзацу.** Счёт растёт заходами, а
188
+ слово стоит на месте: «семь» простояло над восемью перечисленными до самого итога и поехало бы
189
+ дальше — в отчёт и в замысел эпика. Пишется либо перечень без числа, либо число, посчитанное
190
+ тем же ходом, каким пишется итог.
@@ -12,7 +12,8 @@ description: Паттерн правила task-flow. Брать в начале
12
12
 
13
13
  ## Когда брать
14
14
 
15
- - Владелец просит что-то сделать, и работы больше, чем на одну реплику.
15
+ - Владелец просит что-то сделать; размер просьбы значения не имеет папка заводится под любую
16
+ работу.
16
17
  - Замеченный по ходу дефект становится задачей.
17
18
 
18
19
  ## Порядок
@@ -33,21 +34,30 @@ Agent(subagent_type: "Explore", prompt: "<тема просьбы>: что по
33
34
 
34
35
  Находки складываются в раздел «Что уже есть в дереве» разбора.
35
36
 
37
+ Дерево — не единственное место, где может лежать ответ. Решение, принятое прошлым заходом и
38
+ никуда не записанное, живёт только в записи того захода: записи заходов лежат в каталоге заходов
39
+ агента, и поиск по ним словом темы стоит одной команды. Найденное там ответом не остаётся на
40
+ месте — тем же ходом оно переписывается в дерево: в замысел эпика, если связывает задачи, и в
41
+ ход работы, если касается одной.
42
+
43
+ Разведка, не нашедшая ничего, разрешением спрашивать не становится. Сначала называется, где
44
+ искали, потом добираются места, которых в списке не было: замысел эпика, описание прошлого,
45
+ записи прошлых заходов. Одно место отрицанием не является: «в таком-то месте не нашёл» говорит о
46
+ месте, а не о дереве, и вопрос называет оба способа, которыми искали.
47
+
36
48
  Разведка кончается не ощущением, а выводом команд. До первого вопроса владельцу исполнитель
37
49
  знает: как устроен репозиторий (корневая памятка), что лежит в каталоге, о котором пойдёт речь
38
- (`ls`), и есть ли уже написанное по теме (поиск по документации и правилам). Вопрос называет,
39
- где искали: «в таком-то месте не нашёл» проверяемо, «не знаю» нет. Без списка того, что
40
- считается сделанным, разведка исполняется как настроение: прочитанный переданный текст сходит
41
- за неё, и по текущему дереву не запускается ни одной команды.
50
+ (`ls`), и есть ли уже написанное по теме (поиск по документации и правилам). «Не знаю»
51
+ проверяемым не бывает. Без списка того, что считается сделанным, разведка исполняется как
52
+ настроение: прочитанный переданный текст сходит за неё, и по текущему дереву не запускается ни
53
+ одной команды.
42
54
 
43
55
  Разведка по заведённой задаче кончается воспроизведённым симптомом, а не найденным файлом. Тело
44
- задачи описывает дерево на день заведения, и между заведением и работой в главную ветку въезжают
45
- чужие правки: разведка, читающая код по именам из тела, подтверждает, что названные файлы на
46
- месте, — и отпавшая задача от живой не отличается ничем. Прежде первой своей правки разведка
47
- повторяет то, на что задача жалуется: зовёт процедуру, читает отданный ответ, гоняет проверку,
48
- которая молчала. Симптом не воспроизвёлся — задача закрывается как отпавшая, и это законный её
49
- исход: чинить нечего, а зелёные проверки после такой правки говорят ровно об этом и ни о чём
50
- больше.
56
+ задачи описывает дерево на день заведения, и чужие правки въезжают в главную ветку между
57
+ заведением и работой: разведка по именам из тела подтверждает, что файлы на месте, — и отпавшая
58
+ задача от живой не отличается ничем. Прежде первой своей правки разведка повторяет то, на что
59
+ задача жалуется: зовёт процедуру, читает ответ, гоняет молчавшую проверку. Симптом не
60
+ воспроизвёлся — задача закрывается отпавшей, и это законный её исход.
51
61
 
52
62
  **Следующее движение:** находки ложатся в разбор, и тем же ходом владельцу уходит первый из
53
63
  шести вопросов. Разведка кончилась — состояние осталось прежним, ход тоже.
@@ -68,9 +78,21 @@ Agent(subagent_type: "Explore", prompt: "<тема просьбы>: что по
68
78
  | Чем будет видно, что задача закрыта | «работает» признаком не является |
69
79
  | Есть ли образец, с которого снимается подход | разведка найдёт похожее, а не то |
70
80
 
71
- Форму вопроса задают настройки владельца: где они требуют меню, спрашивается меню, и тогда к
72
- каждому вопросу добавляется свободный вариант у закрытого набора нет строки «вопрос не тот».
73
- Выбор слова, имени и термина уточняется прозой в любом случае.
81
+ Список шести набор того, что должно быть закрыто к началу работы, а не набор реплик, которые
82
+ надо произнести. Обязательный вопрос, ответ на который владелец уже дал, отмечается закрытым, а
83
+ не задаётся: ответ ищется в двух местах — в документации и в том, что владелец сказал в этом же
84
+ заходе, включая исходную просьбу. Слово, повторённое в просьбе несколько раз, ответом является.
85
+ Закрытый вопрос отмечается в разборе просьбы вместе с тем, чем он закрыт.
86
+
87
+ Закрыть его можно и допущением, когда ответ очевиден: в разборе стоит строка «вопрос закрыт
88
+ допущением: <что принято>». Неверное допущение стоит правки, вопрос ради очевидного — захода.
89
+
90
+ Объём работы основанием для вопроса о границах не бывает: «это большая работа» решает
91
+ исполнитель, «делать ли её целиком» — владелец, и решает раньше, чем работа началась. Вопрос о
92
+ границах задаётся, когда владелец их не назвал, а не когда названные оказались широкими.
93
+
94
+ Форму вопроса задают настройки владельца: где требуют меню, спрашивается меню, и к каждому
95
+ вопросу добавляется свободный вариант — у закрытого набора нет строки «вопрос не тот».
74
96
 
75
97
  **Рамка переданного текста на текущее дерево не переносится.** Передача захода, файл
76
98
  предложений и спек описывают то дерево, в котором писались. Про текущее знает только текущее:
@@ -121,6 +143,11 @@ Workflow(name: "plan", args: "docs/tasks/_draft-<slug>")
121
143
  «не входит». Находка критика, расходящаяся с ответом владельца, относится владельцу — она не
122
144
  исполняется молча и не считается закрытой правкой текста.
123
145
 
146
+ Ход на этой границе не кончается. Закрытый разбор выглядит законченным куском: ответы владельца
147
+ лежат на диске, файл закоммичен, отчитаться есть чем — и отчёт встаёт ровно на то место, которое
148
+ должна была занять договорённость. Пишется она тем же ходом, конвейером ролей или рукой
149
+ исполнителя, и разницы между этими двумя случаями для конца хода нет.
150
+
124
151
  **Следующее движение:** сверенная с разбором договорённость коммитится, и тем же ходом
125
152
  заводятся задача, ветка и папка — а вышла из разбора серия, сперва объявляется эпик.
126
153
 
@@ -155,6 +182,13 @@ Workflow(name: "plan", args: "docs/tasks/_draft-<slug>")
155
182
  таблицы, с меткой эпика. Выданные номера возвращаются в ту же таблицу — колонкой или приставкой
156
183
  к названию, — и с этой минуты «взять следующую» отвечает номером, а не названием.
157
184
 
185
+ Задача, заведённая под эпик, называет его в своём теле: номер карточки эпика и путь к замыслу —
186
+ одной строкой. Замысел называет задачу со своей стороны, и односторонняя привязка выглядит целой
187
+ ровно так же, как двусторонняя — читатель приходит то от линии работ, то от карточки, и вторая
188
+ сторона существует только для одного из них. Держалась она подражанием: пока тело писалось с
189
+ образца соседней задачи того же эпика, строка копировалась вместе с формой, а задача, заведённая
190
+ посреди работы находкой сверки, писалась не с образца.
191
+
158
192
  **Следующее движение:** объявленный эпик коммитится вместе с номерами задач, и тем же ходом
159
193
  берётся первая его задача — заведением ветки и папки.
160
194
 
@@ -208,6 +242,13 @@ cp docs/tasks/_template/progress.md docs/tasks/<КЛЮЧ>-<номер>-<slug>/pr
208
242
  **Поведение:** меняется
209
243
  ```
210
244
 
245
+ Дерево, у которого каталога «предложено» нет, называет договорённость самим спеком домена — там
246
+ она пишется прямо в него, и переезжать при закрытии работы нечему:
247
+
248
+ ```markdown
249
+ **Спек:** `docs/specs/bookings/spec.md`
250
+ ```
251
+
211
252
  Работа, не задевающая `apps/**` и `libs/**`, договорённости не требует:
212
253
 
213
254
  ```markdown
@@ -242,19 +283,16 @@ cp docs/tasks/_template/progress.md docs/tasks/<КЛЮЧ>-<номер>-<slug>/pr
242
283
  **Следующее движение:** первый этап делается тем же ходом, а закрытым он объявляется после
243
284
  того, как прошла его команда из строки «Чем проверяется».
244
285
 
245
- ## Ловушки
286
+ ## Частые промахи
246
287
 
247
288
  - **Номер не бывает первым.** До конца разбора неизвестно даже, сколько задач из него выйдет:
248
289
  заведённая заранее задача после разбивки закрывается и остаётся мусором в очереди работ.
249
290
  - **Разбор пишется на диск сразу, а не копится в переписке.** Сессия обрывается, и разбор,
250
291
  прожитый в разговоре, восстанавливается только пересказом владельца.
251
292
  - **Из одного разбора вышло несколько задач — общее уезжает в замысел эпика.** Папка задачи
252
- умирает с мержем, а порядок задач и зависимости между ними должны его пережить. Каталог для
253
- замысла называет компаньон правила.
293
+ умирает с мержем, а порядок задач его переживает; каталог называет компаньон правила.
254
294
  - **Задача заводится командой, а не четырьмя вызовами подряд.** Борда к репозиторию не
255
295
  привязана, и задача попадает на неё только явным добавлением.
256
296
  - **Slug ветки берётся из терминологии договорённости, а не из слов просьбы.** Договорённость
257
- пишется раньше ветки и как раз там отказывается от слова владельца: спек завёл своё имя
258
- предмету и прямо сказал, каким словом его не называть, а ветка и папка задачи остались с
259
- отвергнутым. Заголовок задачи и PR поправить можно, имя ветки после открытия PR —
260
- уже нет.
297
+ пишется раньше ветки и как раз там отказывается от слова владельца. Заголовок задачи и PR
298
+ поправить можно, имя ветки после открытия PRуже нет.
@@ -58,6 +58,13 @@ const ALLOW_RENAME: boolean = process.env['E2E_ALLOW_SLUG_RENAME'] === '1';
58
58
  test.skip(!ALLOW_RENAME, 'меняет живой адрес объекта: включается E2E_ALLOW_SLUG_RENAME=1');
59
59
  ```
60
60
 
61
+ Выключатели бывают двух родов, и покрытием считается только первый. **Выключатель по состоянию
62
+ стенда** пропускает случай, которого на этом стенде не бывает по устройству, — сценарий закрыт,
63
+ и отметки он не требует. **Выключатель по переменной окружения** оставляет тест невыполненным:
64
+ сценарий за ним числится покрытым, а не проверен ничем, и такой сценарий несёт отметку
65
+ частичного покрытия с причиной. Из трёх ниже к первому роду не относится ни один: все три
66
+ управляются переменной.
67
+
61
68
  - Спека, необратимо меняющая данные стенда, по умолчанию пропускается и включается своей
62
69
  переменной.
63
70
  - `BEHIND_NGINX` в `home.smoke.spec.ts` — это `!!process.env['BASE_URL']`: вместе с ним
@@ -67,6 +74,22 @@ test.skip(!ALLOW_RENAME, 'меняет живой адрес объекта: в
67
74
  - `playwright/no-skipped-test` выключен в `eslint.config.mjs`: выключатель теста здесь —
68
75
  приём, а не забытый `test.skip`.
69
76
 
77
+ ## Код перехода проверяется ответом, а не переходом по нему
78
+
79
+ Переход браузер проходит сам, и код после него — код конечной страницы: спека, названная
80
+ «отвечает 301», утверждала 200 и не заметила бы подмены постоянного перехода на временный.
81
+ Спрашивается сам ответ, без хождения по нему:
82
+
83
+ ```ts
84
+ const answer = await request.get('/старый-адрес', { maxRedirects: 0 });
85
+
86
+ expect(answer.status()).toBe(301);
87
+ expect(answer.headers()['location']).toBe('/новый-адрес');
88
+ ```
89
+
90
+ Отличать постоянный переход от временного нужно там, где на нём стоит договорённость: поисковые
91
+ роботы и браузер запоминают только постоянный, и разница между 301 и 302 видна лишь в ответе.
92
+
70
93
  ## Частые промахи
71
94
 
72
95
  - **Порт {{ssrPort}} занимать осторожно:** стенд разработчика на {{sitePort}} ходит по тому же имени
@@ -70,7 +70,7 @@ node tools/check-turn-map.mjs # размер, полнота состояни
70
70
  без передачи, без карты, без обеих. Последний случай обязан дать пустой вывод и нулевой код —
71
71
  хук, промолчавший с ненулевым кодом, читается как отбитый запуск.
72
72
 
73
- ## Ловушки
73
+ ## Частые промахи
74
74
 
75
75
  - **Предел размера назначается замером, а не на глаз.** Первое число выбрали «вдвое больше
76
76
  нынешней карты» — и проверка покраснела на собственном тексте в первом же прогоне: карта в