@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
@@ -0,0 +1,93 @@
1
+ ---
2
+ name: git-workflow-pr-ready
3
+ kind: pattern
4
+ rule: git-workflow
5
+ description: Паттерн правила git-workflow. Брать, когда заявки уже открыты: снятие черновика, разбор красного прогона, доведение череды до готовности, порядок «сначала довести отданное, потом брать новое». Открытие одной заявки — паттерн git-workflow-pr, порядок череды — git-workflow-stack.
6
+ ---
7
+
8
+ # Доведение заявки до готовности
9
+
10
+ Паттерн правила `git-workflow`. Что при этом должно быть верно — закон
11
+ `docs/constitution/delivery.md`. Открытие заявки — паттерн `git-workflow-pr`, порядок череды —
12
+ `git-workflow-stack`, разбор одного конфликта — `git-workflow-merge`.
13
+
14
+ ## Когда брать
15
+
16
+ - Заявка открыта черновиком, и прогон по ней кончился.
17
+ - Открыто несколько заявок разом, и надо решить, что делать раньше — доводить их или брать
18
+ следующую задачу.
19
+ - Прогон заявки красный, а правка в ветке зелёная у себя.
20
+
21
+ ## Черновик — состояние работы, а не её вид
22
+
23
+ Черновик говорит одно: работу нельзя вливать. Кнопка слияния у него заблокирована хостингом, и
24
+ владелец, открывший список, видит не «сделано», а «делается». Заявка с зелёным прогоном и
25
+ неснятым черновиком — сделанная работа, выглядящая незаконченной, и поправить это может только
26
+ тот, кто её отдал.
27
+
28
+ Отсюда порядок: **черновик снимается тем же ходом, которым прочитан зелёный прогон.** Не
29
+ следующим, не после соседней задачи.
30
+
31
+ ```bash
32
+ gh pr ready <номер>
33
+ ```
34
+
35
+ Снятие черновика — последний шаг отдачи работы, а не отдельное дело. Пока он не сделан, работа
36
+ не отдана, сколько бы коммитов ни лежало в ветке.
37
+
38
+ ## Сначала довести отданное, потом брать новое
39
+
40
+ Открытая заявка — работа в полёте: её прогон стареет, её ветка отстаёт от главной, её тело
41
+ описывает дерево на день написания. Всё это чинится дёшево сегодня и дорого через три задачи.
42
+
43
+ Очередь поэтому такая:
44
+
45
+ 1. Прогоны открытых заявок прочитаны, черновики с зелёных сняты.
46
+ 2. Красные разобраны и починены.
47
+ 3. И только потом берётся следующая задача.
48
+
49
+ Взять новую задачу, оставив позади десяток заявок черновиками, — значит отчитаться о работе,
50
+ которой у владельца нет: он видит список «делается», а не список «готово».
51
+
52
+ ## Состояние читается разом
53
+
54
+ Чем оно читается и как разбирается каждое поле — паттерн `git-workflow-freshness`; здесь
55
+ только то, что делают с прочитанным. Пустой прогон разбирается наравне с красным: у заявки
56
+ череды база не главная ветка, и фильтр по базе такое событие до конвейера не пропускает.
57
+
58
+ ## Красный прогон разбирается по шагу, а не по заявке
59
+
60
+ ```bash
61
+ gh pr checks <номер>
62
+ ```
63
+
64
+ Ответ называет упавший прогон и ссылку на него. Дальше у хостинга спрашивается имя упавшего
65
+ шага — `gh api` по этому прогону, отбором `select(.conclusion=="failure")` по его шагам.
66
+
67
+ Имя шага и есть диагноз. Правка идёт в ту ветку череды, где причина возникла, а не в ту, где
68
+ прогон покраснел: у череды красным становится всё, что стоит выше причины.
69
+
70
+ ## Правка причины — в нижнюю ветку, оттуда волной вверх
71
+
72
+ Причина, общая для всей череды, чинится один раз в самой нижней ветке. Наверх она едет
73
+ вливанием, а не перебазированием: перебазирование переписывает историю уже отданных веток, и
74
+ хостинг закрывает заявки верхних как слитые, хотя в главной их правок нет.
75
+
76
+ Волна идёт снизу вверх, по одной ветке, и каждый шаг — три отдельных вызова: переключение на
77
+ следующую ветку череды, вливание предыдущей в неё, отправка. Одной строкой их не пишут: гард
78
+ поставки такую команду отбивает, и правильно — набор проверок гоняется по тому дереву, какое
79
+ лежит на момент разбора команды, то есть по прежней ветке.
80
+
81
+ Пропущенная посередине ветка оставляет свою заявку красной и ломает порядок вливания, поэтому
82
+ волна проходит череду целиком.
83
+
84
+ ## Частые промахи
85
+
86
+ - Черновик не снят, потому что «ещё гоняется прогон». Прогон кончился час назад; читается его
87
+ состояние, а не память о том, что он шёл.
88
+ - Взята следующая задача, а десяток заявок остался черновиками. Для владельца сделанного нет.
89
+ - Красное чинится в той ветке, где покраснело. У череды это верхняя, а причина — в нижней, и
90
+ починка сверху оставляет красным всё под собой.
91
+ - Причина разослана по веткам перебазированием. Отданные ветки переписаны, заявки закрыты как
92
+ слитые, правок в главной нет.
93
+ - Пустой прогон принят за зелёный. Событие до конвейера не дошло, и заявка не проверена вовсе.
@@ -180,7 +180,7 @@ npm run task:move -- 86 in-review
180
180
  8. **Правка вёрстки подтверждена замером**, а не взглядом, и снята при узком экране — паттерн
181
181
  `browser-verification-measure`.
182
182
  9. **Правка разметки публичного сайта проверена на прод-сборке по всем локалям перевода** —
183
- паттерн `seo-verify`.
183
+ правило видимости в поиске того дерева, где оно есть.
184
184
  10. **PR привязан к рабочему элементу**, ревьювер и исполнитель стоят, а тело собрано по
185
185
  образцу — разделы «Что сделано», «Чем подтверждено» и «Оставшийся шаг». Раздел оставшегося
186
186
  шага к этому моменту говорит, что шагов не осталось: черновик снимается после разбора
@@ -242,7 +242,7 @@ npm run task:move -- 86 in-review
242
242
  8. **Правка вёрстки подтверждена замером**, а не взглядом, и снята при узком экране — паттерн
243
243
  `browser-verification-measure`.
244
244
  9. **Правка разметки публичного сайта проверена на прод-сборке по всем локалям перевода** — паттерн
245
- `seo-verify`.
245
+ правило видимости в поиске того дерева, где оно есть.
246
246
  10. **Тело PR собрано по образцу** — начинается строкой `Closes #<номер>`, несёт разделы «Что
247
247
  сделано», «Чем подтверждено» и «Оставшийся шаг», а метки, ревьювер и исполнитель стоят.
248
248
  Раздел оставшегося шага к этому моменту говорит, что шагов не осталось: черновик снимается
@@ -194,7 +194,7 @@ npm run task:move -- 86 in-review
194
194
  8. **Правка вёрстки подтверждена замером**, а не взглядом, и снята при узком экране — паттерн
195
195
  `browser-verification-measure`.
196
196
  9. **Правка разметки публичного сайта проверена на прод-сборке по всем локалям перевода** —
197
- паттерн `seo-verify`.
197
+ правило видимости в поиске того дерева, где оно есть.
198
198
  10. **Описание MR собрано по образцу** — начинается строкой `Closes #<номер>`, несёт разделы
199
199
  «Что сделано», «Чем подтверждено» и «Оставшийся шаг», а метки, ревьювер и исполнитель
200
200
  стоят. Раздел оставшегося шага к этому моменту говорит, что шагов не осталось: черновик
@@ -34,16 +34,15 @@ Agent(subagent_type: "Explore", prompt: "<тема просьбы>: что по
34
34
 
35
35
  Находки складываются в раздел «Что уже есть в дереве» разбора.
36
36
 
37
- Дерево — не единственное место, где может лежать ответ. Решение, принятое прошлым заходом и
38
- никуда не записанное, живёт только в записи того захода: записи заходов лежат в каталоге заходов
39
- агента, и поиск по ним словом темы стоит одной команды. Найденное там ответом не остаётся на
40
- месте — тем же ходом оно переписывается в дерево: в замысел эпика, если связывает задачи, и в
41
- ход работы, если касается одной.
37
+ Дерево — не единственное место, где лежит ответ. Решение прошлого захода, никуда не записанное,
38
+ живёт только в записи того захода: поиск по ним словом темы стоит одной команды. Найденное тем же
39
+ ходом переписывается в дерево в замысел эпика, если связывает задачи, и в ход работы, если
40
+ касается одной.
42
41
 
43
- Разведка, не нашедшая ничего, разрешением спрашивать не становится. Сначала называется, где
44
- искали, потом добираются места, которых в списке не было: замысел эпика, описание прошлого,
45
- записи прошлых заходов. Одно место отрицанием не является: «в таком-то месте не нашёл» говорит о
46
- месте, а не о дереве, и вопрос называет оба способа, которыми искали.
42
+ Разведка, не нашедшая ничего, разрешением спрашивать не становится: сначала называется, где
43
+ искали, потом добираются места, которых в списке не было замысел эпика, описание прошлого,
44
+ записи прошлых заходов. «В таком-то месте не нашёл» говорит о месте, а не о дереве, и вопрос
45
+ называет оба способа, которыми искали.
47
46
 
48
47
  Разведка кончается не ощущением, а выводом команд. До первого вопроса владельцу исполнитель знает:
49
48
  как устроен репозиторий (корневая памятка), что лежит в каталоге, о котором пойдёт речь (`ls`), и
@@ -52,11 +51,22 @@ Agent(subagent_type: "Explore", prompt: "<тема просьбы>: что по
52
51
  дереву не запускается ни одной команды.
53
52
 
54
53
  Разведка по заведённой задаче кончается воспроизведённым симптомом, а не найденным файлом. Тело
55
- задачи описывает дерево на день заведения, и чужие правки въезжают в главную ветку между
56
- заведением и работой: разведка по именам из тела подтверждает, что файлы на месте, — и отпавшая
57
- задача от живой не отличается ничем. Прежде первой своей правки разведка повторяет то, на что
58
- задача жалуется: зовёт процедуру, читает ответ, гоняет молчавшую проверку. Симптом не
59
- воспроизвёлся — задача закрывается отпавшей, и это законный её исход.
54
+ задачи описывает дерево на день заведения, и разведка по именам из тела подтверждает лишь то, что
55
+ файлы на месте: отпавшая задача от живой этим не отличается. Прежде первой правки разведка
56
+ повторяет то, на что задача жалуется, зовёт процедуру, читает ответ, гоняет молчавшую
57
+ проверку; симптом не воспроизвёлся задача закрывается отпавшей, и это законный исход.
58
+
59
+ Дерево, названное образцом, читается раскладкой целиком — обходом каталогов на два уровня, — и
60
+ только потом идут вопросы о приёмах. Ответ на «как здесь делают вот это» даёт одну папку, а
61
+ обобщённая до карты дерева она врёт: соседняя семья каталогов в неё не попадает, и пропажу
62
+ находит владелец.
63
+
64
+ Выведенное помечается прямо в списке, вместе с тем, чем его подтвердить. Догадка по соседнему
65
+ случаю стоит в одном списке с проверенным, и владелец читает список целиком как проверенный.
66
+
67
+ Шесть вопросов задаются за вычетом тех, на которые ответила разведка: вместо вопроса с готовым
68
+ ответом в разбор идёт строка «беру такой-то ответ, вот откуда». Признак один — есть ли ответ в
69
+ дереве; «задача кажется понятной» им не является ни в ту, ни в другую сторону.
60
70
 
61
71
  **Следующее движение:** находки ложатся в разбор, и тем же ходом владельцу уходит первый из
62
72
  шести вопросов. Разведка кончилась — состояние осталось прежним, ход тоже.
@@ -66,7 +76,7 @@ Agent(subagent_type: "Explore", prompt: "<тема просьбы>: что по
66
76
  Ведёт главный агент: субагент до владельца не достучится. Команда — `/grill-me`, один вопрос
67
77
  за раз, к каждому — свой рекомендуемый ответ с доводом.
68
78
 
69
- Шесть вопросов задаются всегда, даже когда задача кажется понятной:
79
+ Шесть вопросов закрываются все, а задаются те, на которые разведка не ответила:
70
80
 
71
81
  | Вопрос | Зачем |
72
82
  | -------------------------------------------- | -------------------------------------------------------- |
@@ -77,18 +87,14 @@ Agent(subagent_type: "Explore", prompt: "<тема просьбы>: что по
77
87
  | Чем будет видно, что задача закрыта | «работает» признаком не является |
78
88
  | Есть ли образец, с которого снимается подход | разведка найдёт похожее, а не то |
79
89
 
80
- Список шести — набор того, что должно быть закрыто к началу работы, а не набор реплик, которые
81
- надо произнести. Обязательный вопрос, ответ на который владелец уже дал, отмечается закрытым, а
82
- не задаётся: ответ ищется в двух местах — в документации и в том, что владелец сказал в этом же
83
- заходе, включая исходную просьбу. Слово, повторённое в просьбе несколько раз, ответом является.
84
- Закрытый вопрос отмечается в разборе просьбы вместе с тем, чем он закрыт.
85
-
86
- Закрыть его можно и допущением, когда ответ очевиден: в разборе стоит строка «вопрос закрыт
87
- допущением: <что принято>». Неверное допущение стоит правки, вопрос ради очевидного — захода.
90
+ Список шести — набор того, что закрыто к началу работы, а не набор реплик, которые надо
91
+ произнести. Вопрос, ответ на который владелец уже дал, отмечается закрытым вместе с тем, чем он
92
+ закрыт: ответ ищется в документации и в сказанном этим же заходом, включая исходную просьбу.
93
+ Закрыть его можно и допущением, когда ответ очевиден, строкой «вопрос закрыт допущением:
94
+ <что принято>»: неверное допущение стоит правки, вопрос ради очевидного захода.
88
95
 
89
96
  Объём работы основанием для вопроса о границах не бывает: «это большая работа» решает
90
- исполнитель, «делать ли её целиком» — владелец, и решает раньше, чем работа началась. Вопрос о
91
- границах задаётся, когда владелец их не назвал, а не когда названные оказались широкими.
97
+ исполнитель, «делать ли её целиком» — владелец, и решает раньше, чем работа началась.
92
98
 
93
99
  Форму вопроса задают настройки владельца: где требуют меню, спрашивается меню, и к каждому
94
100
  вопросу добавляется свободный вариант — у закрытого набора нет строки «вопрос не тот».
@@ -135,16 +141,14 @@ Workflow(name: "plan", args: "docs/tasks/_draft-<slug>")
135
141
  (`spec-critic`) → замысел и разбивка (`project-manager`). Пробелы, которые роли не смогли
136
142
  закрыть, возвращаются владельцу — их относит главный агент.
137
143
 
138
- Договорённость, вышедшая из конвейера, сверяется с `grill.md` построчно до того, как по ней
139
- пойдёт работа. Роль пишет текст, не видя владельца, и способна развернуть его ответ в
140
- противоположный: очередь этапов оказалась перевёрнута, а два пункта из входящих переехали в
141
- «не входит». Находка критика, расходящаяся с ответом владельца, относится владельцу она не
142
- исполняется молча и не считается закрытой правкой текста.
144
+ Договорённость, вышедшая из конвейера, сверяется с `grill.md` построчно до работы по ней: роль
145
+ пишет текст, не видя владельца, и способна развернуть его ответ в противоположный — очередь
146
+ этапов оказывалась перевёрнутой, а входящие пункты переезжали в «не входит». Находка критика,
147
+ расходящаяся с ответом владельца, относится владельцу, а не исполняется молча.
143
148
 
144
- Ход на этой границе не кончается. Закрытый разбор выглядит законченным куском: ответы владельца
145
- лежат на диске, файл закоммичен, отчитаться есть чем — и отчёт встаёт ровно на то место, которое
146
- должна была занять договорённость. Пишется она тем же ходом, конвейером ролей или рукой
147
- исполнителя, и разницы между этими двумя случаями для конца хода нет.
149
+ Ход на этой границе не кончается: закрытый разбор выглядит законченным куском ответы на диске,
150
+ файл закоммичен, отчитаться есть чем, — и отчёт встаёт на место договорённости. Пишется она тем
151
+ же ходом, конвейером ролей или рукой исполнителя.
148
152
 
149
153
  **Следующее движение:** сверенная с разбором договорённость коммитится, и тем же ходом
150
154
  заводятся задача, ветка и папка — а вышла из разбора серия, сперва объявляется эпик.
@@ -179,12 +183,10 @@ Workflow(name: "plan", args: "docs/tasks/_draft-<slug>")
179
183
  таблицы, с меткой эпика. Выданные номера возвращаются в ту же таблицу — колонкой или приставкой
180
184
  к названию, — и с этой минуты «взять следующую» отвечает номером, а не названием.
181
185
 
182
- Задача, заведённая под эпик, называет его в своём теле: номер карточки эпика и путь к замыслу —
183
- одной строкой. Замысел называет задачу со своей стороны, и односторонняя привязка выглядит целой
184
- ровно так же, как двусторонняя — читатель приходит то от линии работ, то от карточки, и вторая
185
- сторона существует только для одного из них. Держалась она подражанием: пока тело писалось с
186
- образца соседней задачи того же эпика, строка копировалась вместе с формой, а задача, заведённая
187
- посреди работы находкой сверки, писалась не с образца.
186
+ Задача под эпиком называет его в своём теле номер карточки и путь к замыслу одной строкой, а
187
+ замысел называет задачу со своей стороны. Односторонняя привязка выглядит целой так же, как
188
+ двусторонняя: читатель приходит то от линии работ, то от карточки, и вторая сторона есть только
189
+ для одного из них.
188
190
 
189
191
  **Следующее движение:** объявленный эпик коммитится вместе с номерами задач, и тем же ходом
190
192
  берётся первая его задача — заведением ветки и папки.
@@ -197,19 +199,17 @@ git checkout -b <КЛЮЧ>-<номер>-<slug>
197
199
  npm run task:move -- <номер> in-progress
198
200
  ```
199
201
 
200
- Тело приходит файлом и пустым не бывает: заведённая пустой задача не говорит ничего ни
201
- исполнителю, ни владельцу, а дописать её потом можно только со слова владельца — и заводится
202
- пустое молча, номером наравне с полным.
202
+ Тело приходит файлом и пустым не бывает: пустая задача не говорит ничего ни исполнителю, ни
203
+ владельцу, а дописать её потом можно только со слова владельца.
203
204
 
204
205
  `task:new` переименовывает `_draft-<slug>` в `<КЛЮЧ>-<номер>-<slug>` и проставляет шапку замысла.
205
206
  Ветка заводится вторым вызовом: составную «завести и сразу коммитить» гард главной ветки
206
207
  отклоняет целиком.
207
208
 
208
- Номер уже выдан — черновика нет и не заводится: папка открывается сразу под именем ветки, а
209
- разбор пишется в неё же. Так начинается половина работ: номер приходит прошлым заходом,
210
- замеченным дефектом или соседней задачей, и шаг с черновиком тогда неисполнимпереименовывать
211
- нечего. Ловушка «номер не бывает первым» сюда не относится: она про то, что задачу не заводят до
212
- разбора, а не про то, что с уже заведённой нельзя работать.
209
+ Номер уже выдан — черновика нет и не заводится: папка открывается сразу под именем ветки. Так
210
+ начинается половина работ: номер приходит прошлым заходом, замеченным дефектом или соседней
211
+ задачей, и переименовывать нечего. Ловушка «номер не бывает первым» сюда не относится она про
212
+ то, что задачу не заводят до разбора.
213
213
 
214
214
  Остальные два файла пишутся, а не кладутся образцом впрок: пустой `plan.md` неотличим от
215
215
  замысла без этапов, а следующий заход доверяет папке задачи. Образец открывается тем же
@@ -33,13 +33,16 @@ description: Паттерн правила testing. Брать при правк
33
33
  ## Прогон
34
34
 
35
35
  ```bash
36
- npx nx e2e site-e2e -- --project=chromium
37
- npx nx e2e admin-e2e -- --project=chromium
38
- BASE_URL=http://localhost:{{dockerSitePort}} npx nx e2e site-e2e -- --project=chromium # против внешнего стенда
36
+ npx nx e2e <цель набора> -- --project=chromium
37
+ BASE_URL=http://localhost:$PROXY_SITE_PORT npx nx e2e <цель набора> -- --project=chromium # против внешнего стенда
39
38
  ```
40
39
 
41
- По умолчанию конфиг идёт на {{sitePort}} и подхватывает уже поднятый сервер. С `BASE_URL` свой сервер
42
- не стартует вовсе.
40
+ Имена целей раннера и номера портов у каждого дерева свои: паттерн их не знает. Дерево называет
41
+ их своим профилем — переменными окружения либо разделом надстройки при этом паттерне, где стоят
42
+ готовые команды с его именами.
43
+
44
+ По умолчанию конфиг идёт на порт стенда сайта и подхватывает уже поднятый сервер. С `BASE_URL`
45
+ свой сервер не запускается.
43
46
 
44
47
  Полный набор админки гоняется **одним воркером** (`--workers=1`): тесты с настоящей сессией
45
48
  правят одни и те же объекты живой базы и в параллельном прогоне мешают друг другу. Одни и те
@@ -107,9 +110,9 @@ expect(answer.headers()['location']).toBe('/новый-адрес');
107
110
 
108
111
  ## Частые промахи
109
112
 
110
- - **Порт {{ssrPort}} занимать осторожно:** стенд разработчика на {{sitePort}} ходит по тому же имени
111
- `ssr:{{ssrPort}}` через `host-gateway`, и пока на нём висит чужой процесс, стенд отдаёт чужую
112
- сборку.
113
+ - **Порт сервера отрисовки занимать осторожно:** стенд разработчика ходит по тому же имени
114
+ `ssr:<порт отрисовки>` через `host-gateway`, и пока на нём висит чужой процесс, стенд отдаёт
115
+ чужую сборку.
113
116
  - Браузер стоит один — chromium; узкий экран — `--project=mobile-chrome`. Ошибка «Executable
114
117
  doesn't exist» разобрана в правиле `testing`: она же приходит после смены версии Playwright.
115
118
  - Спеки админки без сессии пропускаются молча — прогон выглядит успешным, а проверено меньше
@@ -125,6 +128,13 @@ expect(answer.headers()['location']).toBe('/новый-адрес');
125
128
  успевает его прочитать, и тест краснеет через раз. Проверяют либо конечное состояние
126
129
  (`data-state` строки стал `done`), либо то же промежуточное — но на ответе, который тест сам
127
130
  задержал и сам отпускает.
131
+ - **Двойник, перенесённый из спеки в общий файл набора, выходит из-под исключения проверки
132
+ повторов.** Она пропускает файлы спек и читает всё остальное, включая двойники и настройки, а
133
+ сверяет имя объявления — не значение и не назначение. Настройка, лежавшая в спеке под общим
134
+ именем, после переноса совпадает с одноимённой в другом слое, и проверка краснеет на файле,
135
+ которого правка не касалась: разбор такого красного занимает отдельный ход. Имя при переносе
136
+ получает приставку своего набора; строка в список известного не заводится — он только
137
+ сокращается.
128
138
  - **Каталог сборки, удалённый под смонтированным томом, оставляет контейнер с пустым
129
139
  корнем:** стенд отвечает 403 на всё, и падают сразу все тесты. Контейнер после
130
140
  `rm -rf dist/apps/<приложение>` пересоздаётся.
@@ -2,7 +2,7 @@
2
2
  name: ts-procedure
3
3
  kind: pattern
4
4
  rule: typescript-conventions
5
- description: Паттерн правила typescript-conventions. Брать при заведении или правке процедуры Connect на бэкенде: готовый класс с полем метода и обработчиком, зависимости конструктором, имена файла и класса. Доступ к процедуре паттерн permissions-procedure.
5
+ description: Паттерн правила typescript-conventions. Брать при заведении или правке процедуры Connect на бэкенде: готовый класс с полем метода и обработчиком, зависимости конструктором, имена файла и класса. Доступ к процедуре описывает правило доступа того дерева, где оно есть.
6
6
  ---
7
7
 
8
8
  # Процедура Connect
@@ -41,7 +41,8 @@ export class PingProcedure implements IConnectProcedure<typeof HealthService.met
41
41
  }
42
42
  ```
43
43
 
44
- Объявление доступа обязательно, и оно ровно одно паттерн `permissions-procedure`.
44
+ Объявление доступа обязательно, и оно ровно одно; чем оно объявляется, говорит правило
45
+ доступа того дерева, где такое правило есть.
45
46
 
46
47
  ## Почему форма такая
47
48
 
@@ -14,11 +14,10 @@
14
14
  тела задачи в дереве ещё верно.
15
15
 
16
16
  - **Разрешение владельца, оставленное в репозитории, теряется на каждой новой ветке.** Оно
17
- записано номером в файл ветки, а следующая ветка отводится от главной и его не несёт: гард
18
- отбивает работу, которую владелец разрешил, и повторяется это ровно столько раз, сколько
19
- веток заведут до слияния разрешившего коммита. Отказ гарда при этом называет файл и молчит о
20
- том, что запись принадлежит ветке: из его текста это читается как настройка дерева. Пока
21
- разрешение живёт в репозитории, номер дописывается заново в каждую новую ветку.
17
+ записано в файл ветки, а следующая ветка отводится от главной и его не несёт: гард запрещает
18
+ разрешённую работу столько раз, сколько веток заведут до слияния. Отказ называет файл и молчит
19
+ о том, что запись принадлежит ветке. Пока разрешение живёт в репозитории, номер дописывается в
20
+ каждую новую ветку.
22
21
  - **Имя чужого дерева в файлы репозитория не пишется, а путь к образцу — пишется.** Обе вещи
23
22
  живут рядом с передачей захода именно поэтому: там законен полный путь, а в репозитории —
24
23
  только ссылка без имени.
@@ -37,13 +36,11 @@
37
36
  договорённость обязана его пережить: её сценарии получают номера в общей нумерации домена,
38
37
  и на них ссылаются заголовки тестов. Обратное тоже верно — ход работы не кладётся в
39
38
  `proposed/`: спек, в котором завелись шаги, снова становится планом и умирает после мержа.
40
- - **У меню нет строки «вопрос не тот».** Меню годится там, где выбор действительно закрыт;
41
- пока постановка вопроса не подтверждена, отвергнуть её владельцу нечем — он выбирает из
42
- вариантов неверной посылки, и выйти из набора может только руками. Настройки владельца,
43
- требующие меню, требование не снимают: тогда к каждому вопросу добавляется свободный вариант,
44
- и он же — единственное место, где вопрос отвергается целиком. Три вопроса ушли одним меню, у
45
- одного постановка была ложной. Там, где под сомнением сама уместность вопроса, его сперва
46
- проверяют по репликам владельца — и чаще всего не задают.
39
+ - **У меню нет строки «вопрос не тот».** Меню годится там, где выбор закрыт; пока постановка
40
+ вопроса не подтверждена, владельцу нечем её отвергнуть — он выбирает из вариантов неверной
41
+ посылки. Если настройки требуют меню, к каждому вопросу добавляется свободный вариант. Три
42
+ вопроса ушли одним меню, у одного постановка была ложной: уместность вопроса сперва проверяют
43
+ по репликам владельца.
47
44
  - **Субагент вопросов владельцу не задаёт.** Ни роли, ни конвейер до него не достучатся —
48
45
  они возвращают текст главному агенту. Поэтому разбор ведёт главный агент, а роли стоят по
49
46
  обе стороны от него.
@@ -91,11 +88,9 @@
91
88
  соседа.
92
89
 
93
90
  - **Копия образца папки задачи несёт шапку раскладки, и первая же правка отбивается гардом.**
94
- Образец разложен пакетом наравне с остальным разложенным, а гард места правки судит по шапке:
95
- копия под задачу выглядит разложенным файлом, и отказ называет адрес источника пакета — то
96
- есть уводит править образец вместо своей копии. Команда заведения задачи шапку снимает сама,
97
- копирование руками — нет. Правится такая копия только записью заново: правку по месту гард
98
- отбивает и её.
91
+ Копия под задачу выглядит разложенным файлом, и отказ называет адрес источника пакета уводит
92
+ править образец вместо копии. Команда заведения задачи снимает шапку сама, копирование руками
93
+ нет. Такая копия правится только записью заново.
99
94
  - **Имя проекта в признаке готовности этапа спрашивается у сборщика, а не пишется по памяти.**
100
95
  На неизвестное имя сборщик отвечает «задач не запущено» и выходит нулём: команда признака не
101
96
  прогнала ни одной пробы и промолчала так же, как зелёный прогон. Видно это только по числу
@@ -122,19 +117,15 @@
122
117
  профиль дерева, и лежит он вне дерева кода.
123
118
 
124
119
  - **Тело задачи, написанное вперёд замысла, называет способ, и способ стареет раньше дефекта.**
125
- Задача серии заводится за недели до того, как её берут, и к этому дню предложенный ход бывает
126
- уже неверен: привезённое пакетом умеет то, что задача звала написать, названного места в
127
- дереве не осталось, а посылки, на которых ход стоял, разведка не подтверждает. Читается такое
128
- тело как действующее указание, поэтому работа начинается с чтения того файла, к которому
129
- задача относится, а не с исполнения её тела. Расхождение уходит решением по ходу и меняет
130
- способ, но не цель.
120
+ Задачу серии заводят за недели до взятия; к этому дню предложенный способ бывает уже неверен:
121
+ пакет уже умеет то, что задача звала написать, названного места в дереве нет. Работа поэтому
122
+ начинается с чтения файла, к которому задача относится, а не с исполнения её тела. Расхождение
123
+ меняет способ, но не цель.
131
124
 
132
125
  - **Работа, упершаяся в разрешение, доводится до конца без той части, которую разрешение
133
- открывает.** Чужой шаг бывает двух родов: прогон и разбор идут сами и кончатся без
134
- исполнителя, а отбитое разрешение не кончится никогда его ждут, и ход, объявивший об этом,
135
- останавливает работу целиком. Делается всё, что от разрешения не зависит, а непройденное
136
- пишется строками тела заявки — там его читает ревьювер; реплика владельцу живёт до следующего
137
- сообщения и в приёмку не попадает.
126
+ открывает.** Прогон и разбор кончатся сами, а отбитое разрешение не кончится никогда: ход,
127
+ объявивший ожидание, останавливает работу целиком. Делается всё, что от разрешения не зависит;
128
+ непройденное пишется в тело заявки, где его читает ревьювер.
138
129
 
139
130
  - **Слово владельца об устройстве — постановка, а не решение.** Названное им обычно уже живёт
140
131
  в дереве под этим самым словом: у него есть имя на экране, раздел в спеке и поле в модели, и
@@ -144,17 +135,11 @@
144
135
  спрашивается до правки.
145
136
 
146
137
  - **Указание работать по ходу — это указание делать его шаги, включая меняющие историю.**
147
- Отметка сделанного этапа, отправка ветки и открытие заявки ходом предписаны, и отдельного
148
- слова на каждый не требуется: спросить надо о том, чего в ходе нет вовсе. Изъятие приходит
149
- из общего запрета дерева на действие без просьбы, прочитанного как требование буквального
150
- слова, и получается указание, исполненное наполовину. Граница у этого одна: прямое слово
151
- владельца о самом шаге. Сказано «ветку не отправляй» — она не отправляется, сколько бы раз
152
- ход её ни предписывал.
153
-
154
- - **Строка ожидания живёт дольше причины, по которой её написали.** Записанная в ход работы,
155
- она приходит в следующий заход раньше любой реплики и подтверждает себя сама: три указания
156
- подряд не пересилили одну строку на диске. Снимается она тем же ходом, которым владелец
157
- ответил, — а не тем, в котором о ней вспомнили.
138
+ Отметка этапа, отправка ветки и открытие заявки предписаны ходом, отдельного слова на каждый
139
+ не нужно. Общий запрет дерева на действие без просьбы, прочитанный буквально, даёт указание,
140
+ исполненное наполовину. Граница одна: прямое слово владельца о самом шаге «ветку не
141
+ отправляй» действует, сколько бы раз ход её ни предписывал.
142
+
158
143
 
159
144
  - **Очередь работ эпиком не кончается.** Занятый другими исполнителями или законченный эпик
160
145
  означает следующую задачу из очереди, а не остановку: «свободных задач эпика нет» ответом на
@@ -165,6 +150,21 @@
165
150
  колонку разбора и снятие её папки — обязательные шаги закрытия, и оба случаются тем же ходом,
166
151
  которым открывается заявка. Ход, в котором больше ничего нет, работу не двигает, сколько бы
167
152
  команд в нём ни стояло.
153
+ - **Черновик папки без номера теряется молча.** Он лежит вне истории, и его не видят ни борда,
154
+ ни сверка очереди, ни следующий заход. Порог брошенного разбора эту потерю не ловит: работа
155
+ проигрывает соседним поручениям в тот же час, а неделя проходит потом.
156
+ - **Стопка веток стоит дороже, и цена у неё названная.** Заявка в соседнюю ветку не запускает
157
+ конвейер, объявленный на базу главной; слияние базовой ветки закрывает заявку следующей как
158
+ слитую, хотя её правок в главной нет; конфликт от чужого слияния разрешается в каждой ветке
159
+ стопки заново. Расстановка, выбранная молча, собирает всю цену и не показывает ни одной её
160
+ части. Задачи, идущие одна из другой по коду, законно живут ветками от главной, пока правка
161
+ следующей не опирается на код предыдущей.
162
+
163
+ - **Находка посреди этапа ощущается частью текущей работы, когда предмет соседний.** Своего
164
+ признака у этого нет: до первой правки находки в дереве нет, а после неё файлы соседней работы
165
+ от файлов своей не отличаются. Поэтому сверяется перечень условий выхода замысла, а не ощущение.
166
+ Однажды такую правку остановил посторонний отказ по роду файла, а не сверка с замыслом: без него
167
+ она уехала бы в чужую ветку, и раздельного отката у двух работ не было бы.
168
168
 
169
169
  ## Поведение исполнителя — по разборам происшествий
170
170
 
@@ -207,7 +207,7 @@
207
207
  перечисляет шесть обязательных вопросов таблицей, и пустая таблица проходит наравне с
208
208
  заполненной.
209
209
  - **Отказ гарда разговора исполняется задним числом.** Владелец видит незаданный вопрос вместе с
210
- отбитым ходом: прозаический вопрос инструментом не является, и раньше поймать его нечем. Гард
210
+ отбитым ходом: прозаический вопрос не вызов инструмента, и раньше поймать его нечем. Гард
211
211
  отмечает пропуск, но не отменяет его.
212
212
  - **Обход требования папки нужен там, где работа вливается частями.** Тогда её до конца не
213
213
  разбирают, а причина остаётся в заявке.