@rt-tools/agent-kit 0.11.0 → 0.12.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 (115) hide show
  1. package/assets/checks/check-file-size.mjs +19 -4
  2. package/assets/checks/check-state-next.mjs +10 -2
  3. package/assets/checks/rt-kit-checks.config.mjs +16 -2
  4. package/assets/defaults/project.sh +9 -1
  5. package/assets/defaults/turn-map.md +8 -6
  6. package/assets/hooks/browser-guard-device-id.sh +3 -1
  7. package/assets/hooks/browser-guard-no-asking.sh +3 -1
  8. package/assets/hooks/browser-guard-no-other-drivers.sh +5 -3
  9. package/assets/hooks/browser-guard-require-select.sh +4 -2
  10. package/assets/hooks/claim-guard.sh +3 -1
  11. package/assets/hooks/conscience-guard.sh +3 -1
  12. package/assets/hooks/dev-server-guard.sh +5 -3
  13. package/assets/hooks/dispatch.sh +69 -0
  14. package/assets/hooks/docs-guard.sh +6 -4
  15. package/assets/hooks/exam-guard.sh +5 -3
  16. package/assets/hooks/git-guard-delivery.sh +37 -5
  17. package/assets/hooks/git-guard-main.sh +6 -4
  18. package/assets/hooks/git-guard-push-tests.sh +6 -4
  19. package/assets/hooks/grill-gate.sh +4 -2
  20. package/assets/hooks/handoff-entry-guard.sh +4 -2
  21. package/assets/hooks/handoff-write.sh +27 -6
  22. package/assets/hooks/hook-input.sh +54 -0
  23. package/assets/hooks/lint-after-edit.sh +5 -3
  24. package/assets/hooks/postmortem-guard.sh +3 -1
  25. package/assets/hooks/proposal-guard.sh +3 -1
  26. package/assets/hooks/prose-style-guard.sh +5 -3
  27. package/assets/hooks/qa-dataid-guard.sh +4 -2
  28. package/assets/hooks/rerun-guard.sh +5 -3
  29. package/assets/hooks/reuse-first-guard.sh +5 -3
  30. package/assets/hooks/rule-article.sh +99 -0
  31. package/assets/hooks/skill-gate-rearm.sh +3 -1
  32. package/assets/hooks/skill-gate.sh +23 -2
  33. package/assets/hooks/skill-loaded.sh +3 -1
  34. package/assets/hooks/sql-guard-request.sh +2 -1
  35. package/assets/hooks/sql-guard.sh +4 -2
  36. package/assets/hooks/task-flow-guard.sh +6 -4
  37. package/assets/hooks/turn-exit-guard.sh +42 -17
  38. package/assets/hooks/waiting-turn-guard.sh +3 -1
  39. package/assets/hooks/window-fill-guard.sh +6 -4
  40. package/assets/laws/work-conduct.md +5 -9
  41. package/assets/patterns/dependencies-upgrade.md +1 -1
  42. package/assets/patterns/doc-style-write.md +3 -3
  43. package/assets/patterns/git-workflow-commit.azure.md +2 -202
  44. package/assets/patterns/git-workflow-commit.github.md +2 -258
  45. package/assets/patterns/git-workflow-commit.gitlab.md +1 -217
  46. package/assets/patterns/git-workflow-docker.md +3 -3
  47. package/assets/patterns/git-workflow-merge.md +3 -2
  48. package/assets/patterns/git-workflow-migration.md +3 -3
  49. package/assets/patterns/git-workflow-pr.azure.md +224 -0
  50. package/assets/patterns/git-workflow-pr.github.md +280 -0
  51. package/assets/patterns/git-workflow-pr.gitlab.md +240 -0
  52. package/assets/patterns/git-workflow-restart.md +3 -3
  53. package/assets/patterns/git-workflow-secrets.md +3 -3
  54. package/assets/patterns/task-flow-archive.md +193 -0
  55. package/assets/patterns/task-flow-close.md +3 -173
  56. package/assets/patterns/task-flow-handoff.md +4 -4
  57. package/assets/pitfalls/doc-style.md +80 -0
  58. package/assets/pitfalls/git-workflow.azure.md +50 -0
  59. package/assets/pitfalls/git-workflow.github.md +78 -0
  60. package/assets/pitfalls/git-workflow.gitlab.md +49 -0
  61. package/assets/pitfalls/spec-driven.md +36 -0
  62. package/assets/pitfalls/styling-bem.md +45 -0
  63. package/assets/pitfalls/task-flow.md +62 -0
  64. package/assets/pitfalls/testing.md +70 -0
  65. package/assets/rules/deploy-flow.azure.md +106 -0
  66. package/assets/rules/deploy-flow.github.md +113 -0
  67. package/assets/rules/deploy-flow.gitlab.md +108 -0
  68. package/assets/rules/doc-style.md +25 -76
  69. package/assets/rules/git-workflow.azure.md +6 -92
  70. package/assets/rules/git-workflow.github.md +14 -127
  71. package/assets/rules/git-workflow.gitlab.md +6 -93
  72. package/assets/rules/spec-driven.md +39 -30
  73. package/assets/rules/styling-bem.md +20 -39
  74. package/assets/rules/task-flow.md +17 -199
  75. package/assets/rules/testing.md +3 -64
  76. package/assets/rules/turn-conduct.md +206 -0
  77. package/assets/rules/typescript-conventions.md +15 -0
  78. package/assets/skills/agent-kit.md +35 -12
  79. package/assets/templates/pitfalls.md +10 -0
  80. package/assets/templates/rule.md +5 -3
  81. package/bin/agent-kit.d.ts.map +1 -1
  82. package/bin/agent-kit.js +1 -42
  83. package/bin/agent-kit.js.map +1 -1
  84. package/lib/assets.d.ts.map +1 -1
  85. package/lib/assets.js +6 -1
  86. package/lib/assets.js.map +1 -1
  87. package/lib/cascade.d.ts.map +1 -1
  88. package/lib/cascade.js +19 -1
  89. package/lib/cascade.js.map +1 -1
  90. package/lib/commands.d.ts.map +1 -1
  91. package/lib/commands.js +1 -0
  92. package/lib/commands.js.map +1 -1
  93. package/lib/config.d.ts +16 -1
  94. package/lib/config.d.ts.map +1 -1
  95. package/lib/config.js +8 -0
  96. package/lib/config.js.map +1 -1
  97. package/lib/hooks-map.d.ts +13 -0
  98. package/lib/hooks-map.d.ts.map +1 -1
  99. package/lib/hooks-map.js +33 -1
  100. package/lib/hooks-map.js.map +1 -1
  101. package/lib/ship.d.ts +1 -2
  102. package/lib/ship.d.ts.map +1 -1
  103. package/lib/ship.js +0 -54
  104. package/lib/ship.js.map +1 -1
  105. package/package.json +1 -1
  106. package/rt-tools-agent-kit-0.12.0.tgz +0 -0
  107. package/assets/commands/agent-kit-digest.md +0 -89
  108. package/assets/commands/rules-review.md +0 -98
  109. package/assets/patterns/cargo-triage-mark.md +0 -119
  110. package/assets/rules/cargo-triage.md +0 -126
  111. package/lib/cargo-state.d.ts +0 -62
  112. package/lib/cargo-state.d.ts.map +0 -1
  113. package/lib/cargo-state.js +0 -118
  114. package/lib/cargo-state.js.map +0 -1
  115. package/rt-tools-agent-kit-0.11.0.tgz +0 -0
@@ -22,16 +22,21 @@
22
22
  # 5. Передача захода написана — окно кончилось.
23
23
  # 6. Владелец сказал остановиться.
24
24
  #
25
- # Чего страж не судит. Заход вне ветки задачи и работу без папки: состояние там объявлять
26
- # негде, и отбивать было бы не за что. Это его известная граница.
25
+ # Работа без ветки и без папки задачи судится вторым признаком. Состояния у неё нет, и первый
26
+ # признак взять неоткуда, но ход, в котором не было ни одной правки дерева, не кончается и
27
+ # здесь: просьба владельца «разложи», «обнови», «посмотри» живёт без задачи и без ветки, и
28
+ # защищена она была меньше всего. Отпускают такой ход те же четыре вещи: вопрос, отказ гарда,
29
+ # написанная передача и слово владельца об остановке.
27
30
  #
28
31
  # ОТКАЗ В ПОЛЬЗУ РАБОТЫ: при любой ошибке, нехватке `jq`, отсутствии записи хода, папки задачи
29
32
  # или строки состояния ход РАЗРЕШАЕТСЯ (exit 0). Сломанный страж не имеет права заклинить
30
33
  # разговор.
31
34
 
32
35
  . "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/utf8.sh" 2>/dev/null || true
36
+ . "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/hook-input.sh" 2>/dev/null || true
33
37
 
34
- input="$(cat 2>/dev/null)"
38
+ rt_hook_read
39
+ input="$RT_HOOK_INPUT"
35
40
  [ -z "$input" ] && exit 0
36
41
  command -v jq >/dev/null 2>&1 || exit 0
37
42
 
@@ -43,22 +48,25 @@ transcript="$(printf '%s' "$input" | jq -r '.transcript_path // empty' 2>/dev/nu
43
48
  [ -z "$transcript" ] && exit 0
44
49
  [ -f "$transcript" ] || exit 0
45
50
 
46
- workdir="$(printf '%s' "$input" | jq -r '.cwd // empty' 2>/dev/null)"
51
+ workdir="$(rt_hook_cwd)"
47
52
  [ -z "$workdir" ] && workdir="${CLAUDE_PROJECT_DIR:-.}"
48
53
  cd "$workdir" 2>/dev/null || exit 0
49
54
  git rev-parse --is-inside-work-tree >/dev/null 2>&1 || exit 0
50
55
 
51
- branch="$(git branch --show-current 2>/dev/null)"
52
- [ -z "$branch" ] && exit 0
53
-
54
56
  root="$(git rev-parse --show-toplevel 2>/dev/null)"
55
57
  [ -z "$root" ] && exit 0
56
- tasks_dir="${RT_TASKS_DIR:-docs/tasks}"
57
- progress="$root/$tasks_dir/$branch/progress.md"
58
- [ -f "$progress" ] || exit 0
59
58
 
60
- state="$(sed -n 's/^[[:space:]]*[-*][[:space:]]*\*\*Состояние:\*\*[[:space:]]*`\([^`]*\)`.*/\1/p' "$progress" 2>/dev/null | head -1)"
61
- [ -z "$state" ] && exit 0
59
+ # Ветка, папка задачи и строка состояния берутся, пока они есть. Пусто — ход судится вторым
60
+ # признаком, а не отпускается: отсюда раньше уходили нулём, и работа по слову владельца
61
+ # кончалась объявлением намерения молча.
62
+ branch="$(git branch --show-current 2>/dev/null)"
63
+ tasks_dir="${RT_TASKS_DIR:-docs/tasks}"
64
+ progress=""
65
+ state=""
66
+ if [ -n "$branch" ] && [ -f "$root/$tasks_dir/$branch/progress.md" ]; then
67
+ progress="$root/$tasks_dir/$branch/progress.md"
68
+ state="$(sed -n 's/^[[:space:]]*[-*][[:space:]]*\*\*Состояние:\*\*[[:space:]]*`\([^`]*\)`.*/\1/p' "$progress" 2>/dev/null | head -1)"
69
+ fi
62
70
 
63
71
  # Работа, дошедшая до этих двух состояний, чужого шага уже дождалась: дальше её двигает
64
72
  # владелец, и ход, закрытый здесь, ничего не роняет.
@@ -68,7 +76,8 @@ esac
68
76
 
69
77
  # Следующий шаг из хода работы — его страж и называет в отказе: исполнитель, которому сказано
70
78
  # только «работа не кончена», перечитывает ту же строку сам.
71
- next_step="$(sed -n 's/^[[:space:]]*[-*][[:space:]]*\*\*Следующий шаг:\*\*[[:space:]]*\(.*\)/\1/p' "$progress" 2>/dev/null | head -1)"
79
+ next_step=""
80
+ [ -n "$progress" ] && next_step="$(sed -n 's/^[[:space:]]*[-*][[:space:]]*\*\*Следующий шаг:\*\*[[:space:]]*\(.*\)/\1/p' "$progress" 2>/dev/null | head -1)"
72
81
  [ -z "$next_step" ] && next_step="что стоит в разделе «Где стоим» хода работы"
73
82
 
74
83
  # Команда, меняющая дерево или его состояние. Чтение и поиск сюда не входят намеренно: ими и
@@ -119,10 +128,14 @@ commands="$(printf '%s' "$verdict" | jq -r '.ran // ""' 2>/dev/null)"
119
128
  # Страж сравнивает номер этапа с тем, что лежит в истории ветки, и на выросшем номере требует
120
129
  # команды из строки «Чем проверяется» — она стоит в замысле обратными кавычками. Приём, записанный
121
130
  # прозой, страж не читает: подтвердить его выводом нечем, и это его известная граница.
122
- stage_now="$(sed -n 's/^[[:space:]]*[-*][[:space:]]*\*\*Этап:\*\*[[:space:]]*\([0-9][0-9]*\).*/\1/p' "$progress" 2>/dev/null | head -1)"
123
- stage_was="$(git -C "$root" show "HEAD:$tasks_dir/$branch/progress.md" 2>/dev/null | sed -n 's/^[[:space:]]*[-*][[:space:]]*\*\*Этап:\*\*[[:space:]]*\([0-9][0-9]*\).*/\1/p' | head -1)"
131
+ stage_now=""
132
+ stage_was=""
133
+ if [ -n "$progress" ]; then
134
+ stage_now="$(sed -n 's/^[[:space:]]*[-*][[:space:]]*\*\*Этап:\*\*[[:space:]]*\([0-9][0-9]*\).*/\1/p' "$progress" 2>/dev/null | head -1)"
135
+ stage_was="$(git -C "$root" show "HEAD:$tasks_dir/$branch/progress.md" 2>/dev/null | sed -n 's/^[[:space:]]*[-*][[:space:]]*\*\*Этап:\*\*[[:space:]]*\([0-9][0-9]*\).*/\1/p' | head -1)"
136
+ fi
124
137
 
125
- if [ -n "$stage_now" ] && [ -n "$stage_was" ] && [ "$stage_now" -gt "$stage_was" ] 2>/dev/null; then
138
+ if [ -n "$progress" ] && [ -n "$stage_now" ] && [ -n "$stage_was" ] && [ "$stage_now" -gt "$stage_was" ] 2>/dev/null; then
126
139
  plan="$root/$tasks_dir/$branch/plan.md"
127
140
  # Контракт закрытого этапа, а не начатого: подтверждается то, что объявлено сделанным.
128
141
  contract="$(awk -v n="$stage_was" '
@@ -164,7 +177,18 @@ fi
164
177
 
165
178
  [ "$worked" = "true" ] && exit 0
166
179
 
167
- reason="BLOCKED by turn-exit-guard: работа в состоянии '${state}', а за этот ход по ней не сделано ничего — ни правки, ни команды, меняющей дерево.
180
+ if [ -z "$state" ]; then
181
+ reason="BLOCKED by turn-exit-guard: за этот ход не сделано ничего — ни правки, ни команды, меняющей дерево. Папки задачи у этой работы нет, и состояние взять неоткуда, но ход это не кончает.
182
+
183
+ Ход кончается четырьмя способами, и других нет: вопрос владельцу, ответа на который в правилах нет; отказ гарда; заполненное окно захода; отданная работа с начатой следующей. Названная и не запущенная команда выходом не является: строка «сейчас запущу» — объявление намерения, а оно прямо названо ложным концом хода.
184
+
185
+ Работа по слову владельца — «разложи», «обнови», «посмотри» — идёт без задачи и без ветки, и остановить её нечем, кроме этого признака.
186
+
187
+ Запусти названное этим же ходом. Владелец сказал остановиться — так и напиши: страж читает его слово, а не пересказ.
188
+
189
+ Страж судит один ход: следующий заход не отбивается."
190
+ else
191
+ reason="BLOCKED by turn-exit-guard: работа в состоянии '${state}', а за этот ход по ней не сделано ничего — ни правки, ни команды, меняющей дерево.
168
192
 
169
193
  Ход кончается четырьмя способами, и других нет: вопрос владельцу, ответа на который в правилах нет; отказ гарда; заполненное окно захода; отданная работа с начатой следующей. Отчёт о сделанном выходом не является — он выглядит работой лучше всякой другой, и пустоты за ним не видно.
170
194
 
@@ -173,6 +197,7 @@ reason="BLOCKED by turn-exit-guard: работа в состоянии '${state}
173
197
  Сделай его этим же ходом. Владелец сказал остановиться — так и напиши: страж читает его слово, а не пересказ.
174
198
 
175
199
  Страж судит один ход: следующий заход не отбивается."
200
+ fi
176
201
 
177
202
  # Общий хвост отказа: два законных хода. Файл может быть не разложен — тогда хвоста нет,
178
203
  # а причина отказа остаётся прежней.
@@ -31,8 +31,10 @@
31
31
  # заходе ход РАЗРЕШАЕТСЯ (exit 0). Сломанный гард не имеет права заклинить разговор.
32
32
 
33
33
  . "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/utf8.sh" 2>/dev/null || true
34
+ . "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/hook-input.sh" 2>/dev/null || true
34
35
 
35
- input="$(cat 2>/dev/null)"
36
+ rt_hook_read
37
+ input="$RT_HOOK_INPUT"
36
38
  [ -z "$input" ] && exit 0
37
39
 
38
40
  command -v jq >/dev/null 2>&1 || exit 0
@@ -30,8 +30,10 @@
30
30
  # работа РАЗРЕШАЕТСЯ (exit 0). Сломанный гард не имеет права заклинить работу.
31
31
 
32
32
  . "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/utf8.sh" 2>/dev/null || true
33
+ . "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/hook-input.sh" 2>/dev/null || true
33
34
 
34
- input="$(cat 2>/dev/null)"
35
+ rt_hook_read
36
+ input="$RT_HOOK_INPUT"
35
37
  [ -z "$input" ] && exit 0
36
38
 
37
39
  command -v jq >/dev/null 2>&1 || exit 0
@@ -144,9 +146,9 @@ fi
144
146
  [ "$event" = "PreToolUse" ] || exit 0
145
147
  [ "$pct" -ge "$stop_pct" ] || exit 0
146
148
 
147
- tool="$(printf '%s' "$input" | jq -r '.tool_name // empty' 2>/dev/null)"
148
- path="$(printf '%s' "$input" | jq -r '.tool_input.file_path // empty' 2>/dev/null)"
149
- cmd="$(printf '%s' "$input" | jq -r '.tool_input.command // empty' 2>/dev/null)"
149
+ tool="$(rt_hook_tool)"
150
+ path="$(rt_hook_file)"
151
+ cmd="$(rt_hook_cmd)"
150
152
 
151
153
  allowed=0
152
154
  case "$tool" in
@@ -1,9 +1,7 @@
1
1
  # Закон о ведении работы
2
2
 
3
- Что должно быть верно про то, как работа идёт от просьбы владельца до её закрытия. Работа
4
- длится дольше одного захода и переживает перерывы: между заходами исполнитель не помнит
5
- ничего, а владелец помнит и вынужден пересказывать. Пересказ каждый раз выходит короче
6
- предыдущего, и работа доделывается по обрывку исходной просьбы.
3
+ Закон устанавливает как ведётся работа от момента постановки задачи до её закрытия. Работа
4
+ длится дольше одной сессии и должна сохранять весь контекст и состояние при переходах из одной сессии в другую.
7
5
 
8
6
  ## Статьи
9
7
 
@@ -13,15 +11,13 @@
13
11
  - **Пробел закрывается вопросом владельцу, а не догадкой.** Догадка неотличима от знания:
14
12
  она попадает в работу молча и обнаруживается только при приёмке, когда переделывать дороже
15
13
  всего.
16
- - **Работа, объявленная сборкой по образцу, начинается с чтения самого образца.** Пересказ
14
+ - **Работа, которая требует изменений по образцу, начинается с чтения самого образца.** Пересказ
17
15
  образца образцом не является: по нему собирается понимание того, кто пересказывал, и
18
16
  расхождение всплывает на приёмке целой работой, а не строкой. Читается та часть образца,
19
17
  которую работа повторяет, и читается целиком — об устройстве чужого дерева по одному его
20
18
  файлу не судят.
21
- - **Образец, названный однажды, доступен каждому заходу работы.** Где он лежит, записано
22
- там, где заход найдёт это без владельца. Иначе второй заход собирает по памяти первого,
23
- третий — по пересказу второго, и к четвёртому от образца не остаётся ничего, кроме слова
24
- «образец».
19
+ - **Образец, указанный в ходе работы должен быть доступен каждой сессии во время работы.**
20
+ Ссылка на образец нужно указывать непосредственно в файле с описанием прогресса работы.
25
21
  - **Вопрос, у которого есть очевидный ответ, работу не останавливает.** Исполнитель называет
26
22
  допущение, идёт дальше и записывает его туда же, где идёт работа. Останавливает только тот
27
23
  пробел, при котором любая догадка делает работу опасной или бесполезной. Вопрос, заданный
@@ -2,7 +2,7 @@
2
2
  name: dependencies-upgrade
3
3
  kind: pattern
4
4
  rule: dependencies
5
- description: Паттерн правила dependencies. Брать при подъёме версий пакетов — выбор верхней границы по peer-диапазонам, порядок проверок, граница переформатирования после обновления форматтера, разбор новых правил линтера. Не брать для ветки, коммита и PR — это паттерн git-workflow-commit.
5
+ description: Паттерн правила dependencies. Брать при подъёме версий пакетов — выбор верхней границы по peer-диапазонам, порядок проверок, граница переформатирования после обновления форматтера, разбор новых правил линтера. Не брать для ветки и коммита — это паттерн git-workflow-commit, для PR — git-workflow-pr.
6
6
  ---
7
7
 
8
8
  # Подъём версий
@@ -19,7 +19,7 @@ description: Паттерн правила doc-style. Брать при напи
19
19
 
20
20
  Само правило укладывается в одно предложение. Следом — не больше двух предложений о том, что
21
21
  сломается иначе, и только если из самой фразы это не видно. Обоснование, у которого была
22
- альтернатива, идёт в «Ловушки» правила, а не в сам закон: разросшийся буллет читают по
22
+ альтернатива, идёт в ловушки — холодную часть правила, а не в сам закон: разросшийся буллет читают по
23
23
  диагонали, а закон говорит, что верно, — не почему когда-то выбрали так.
24
24
 
25
25
  ```
@@ -41,8 +41,8 @@ description: Паттерн правила doc-style. Брать при напи
41
41
  Место исполнения меняется при первом же рефакторинге, и документ, который его называет,
42
42
  устаревает молча. Для него заведён отдельный файл — `implementation.md` рядом.
43
43
 
44
- Исключение — «Ловушки» правила: там устройство кода называется прямо, потому что ловушка и
45
- есть место, где на него наступают.
44
+ Исключение — ловушки в холодной части правила: там устройство кода называется прямо, потому
45
+ что ловушка и есть место, где на него наступают.
46
46
 
47
47
  ## Без утверждений о будущем
48
48
 
@@ -2,10 +2,10 @@
2
2
  name: git-workflow-commit
3
3
  kind: pattern
4
4
  rule: git-workflow
5
- description: Паттерн правила git-workflow для дерева в Azure DevOps. Брать на заведение рабочего элемента, ветки, коммит, пуш и создание PR — заведение элемента со всеми шагами, перевод по состояниям, слияние двух задач в одну, сверка очереди работ, работа от учётной записи машинной работы, формат заголовка, привязка PR к элементу, ревьювер, исполнитель и метки, образец тела PR с разделом об оставшемся шаге, чеклист проверок до публикации, обход требования документа. Не брать для миграций и перезапуска прода — это паттерны git-workflow-migration и git-workflow-restart.
5
+ description: Паттерн правила git-workflow. Брать на заведение рабочего элемента, ветки, коммит и пуш — заведение элемента с областью и итерацией, перевод состояния, слияние двух задач в одну, работа от учётной записи машинной работы, обход требования документа. Не брать на открытие PR это паттерн git-workflow-pr; не брать для миграций и перезапуска прода — это паттерны git-workflow-migration и git-workflow-restart.
6
6
  ---
7
7
 
8
- # Ветка, коммит и PR
8
+ # Задача, ветка и коммит
9
9
 
10
10
  Паттерн правила `git-workflow`. Что при этом должно быть верно — закон
11
11
  `docs/constitution/delivery.md`.
@@ -15,7 +15,6 @@ description: Паттерн правила git-workflow для дерева в A
15
15
  - Заводится рабочий элемент, с которого начинается правка.
16
16
  - Заводится ветка под него.
17
17
  - Готовится коммит или пуш.
18
- - Открывается PR.
19
18
  - Работа перешла на следующий шаг, и элемент переводится в другое состояние.
20
19
 
21
20
  ## Сначала рабочий элемент, потом ветка
@@ -150,212 +149,13 @@ GIT_COMMITTER_NAME="<бот>" GIT_COMMITTER_EMAIL="<почта бота>" \
150
149
  Docs-skip: правка только в тестах хука, зеркала у него нет
151
150
  ```
152
151
 
153
- ## Номер элемента стоит в его заголовке и в заголовке PR
154
-
155
- Форма одна на оба — `[<номер>] <текст>`. Номер стоит в самом заголовке, а не только в теле: в
156
- списке PR тела не видно. Тот же номер несёт и имя ветки, поэтому элемент, ветка и PR читаются
157
- как одно.
158
-
159
- Элемент говорит, что не так; PR тем же номером отчитывается, что сделано:
160
-
161
- ```
162
- элемент [86] Пустой адрес владельца — письма не уходят молча
163
- PR [86] Письмо владельцу с незаполненным адресом попадает в логи
164
- ```
165
-
166
- Инфинитив в заголовок PR не переносится: «исправить» становится «исправлено», «вернуть» —
167
- «возвращено», «добавить» — «добавлено».
168
-
169
- Тип и область — `fix(site):`, `docs(common):` — в заголовок PR не идут: это формат заголовка
170
- коммита, и там его сверяет `commitlint`.
171
-
172
- ## Не готовое к слиянию открывается черновиком
173
-
174
- Правка кода отдаётся человеку открытым PR: запушенная ветка ему не показывается нигде. Открытый
175
- PR при этом читается как приглашение влить, поэтому у незаконченной работы он открывается
176
- черновиком — завершение у черновика хостинг блокирует сам:
177
-
178
- ```bash
179
- AZURE_DEVOPS_EXT_PAT="$TOKEN" az repos pr create --draft true --title '[<КЛЮЧ>-86] …' \
180
- --description "$(cat тело.md)"
181
- ```
182
-
183
- Конвейер проверок у черновика по умолчанию не запускается: молчание прогона за зелёный прогон
184
- не принимается, и набор гоняется на своей машине либо запуском вручную.
185
-
186
- Черновиком идёт всё, что ждёт прогона конвейера, доработки или ответа на вопрос. Вопрос
187
- задаётся в самом PR, а не остаётся в голове исполнителя: человек читает PR, а не переписку
188
- захода.
189
-
190
- Снимается черновик отдельным вызовом, и это тот самый ход, которым исполнитель говорит, что
191
- решение готово:
192
-
193
- ```bash
194
- AZURE_DEVOPS_EXT_PAT="$TOKEN" az repos pr update --id 86 --draft false
195
- ```
196
-
197
- До снятия молчание исполнителя значит «ещё не готово», после — «можно вливать». Снятие
198
- черновика и просьба влить идут одним ходом: снятый черновик, о котором человеку не сказали,
199
- ждёт разбора ровно так же, как не снятый.
200
-
201
- ## PR привязывается к элементу при создании
202
-
203
- Привязка задаётся флагом, а не правкой после: у токена может не быть права править чужой
204
- элемент, и вторая команда обойдётся молча, оставив PR ни с чем не связанным.
205
-
206
- ```bash
207
- AZURE_DEVOPS_EXT_PAT="$TOKEN" az repos pr create \
208
- --title '[86] Письмо владельцу с незаполненным адресом попадает в логи' \
209
- --source-branch 86-mail-owner-silence --target-branch main \
210
- --work-items 86 --reviewers <владелец> --delete-source-branch true \
211
- --description 'Закрывает рабочий элемент 86.'
212
- ```
213
-
214
- Ревьювер — всегда владелец: без запроса разбора PR не показывается ему в очереди. Один PR
215
- закрывает элемент целиком — половину задачи одним PR не выкатывают: у задачи одна ветка, и
216
- работа, которая в неё не влезает, делится на задачи до того, как ветка заводится.
217
-
218
- У уже открытого PR то же ставится правкой:
219
-
220
- ```bash
221
- az repos pr work-item add --id 205 --work-items 86
222
- az repos pr reviewer add --id 205 --reviewers <владелец>
223
- az repos pr update --id 205 --description "$(cat тело.md)"
224
- ```
225
-
226
- Правка описания переписывает его целиком. Тело перечитывается всякий раз, когда в ветку что-то
227
- влилось после публикации: PR утверждает про дерево, а дерево с тех пор изменилось.
228
-
229
- ## Образец тела PR
230
-
231
- Четыре раздела, и порядок между ними один: строка связи, что сделано, чем подтверждено,
232
- оставшийся шаг. Раздел, которому нечего сказать, пишется словами — пустой заголовок и снятый
233
- заголовок читаются одинаково, а значат разное.
234
-
235
- ```markdown
236
- Закрывает рабочий элемент 86.
237
-
238
- ## Что сделано
239
-
240
- - <правка, названная тем, что она меняет для читателя, а не тем, какие файлы задела>
241
-
242
- ## Чем подтверждено
243
-
244
- - <проверка>: <её вывод одной строкой>
245
- - Не гонялось: <что в набор не вошло и почему>
246
-
247
- ## Оставшийся шаг
248
-
249
- После одобрения ветка получает ещё один коммит — разбор папки задачи, — и только потом
250
- вливается. До этого коммита вливать рано: папка уедет в главную ветку неразобранной.
251
- ```
252
-
253
- Раздел «Оставшийся шаг» стоит последним и переписывается тем же вызовом, что и остальное тело,
254
- — в тот ход, которым папка разбирается и снимается черновик:
255
-
256
- ```markdown
257
- ## Оставшийся шаг
258
-
259
- Не осталось: папка задачи разобрана коммитом `<sha>`, черновик снят. Можно вливать.
260
- ```
261
-
262
- Стоит он там потому, что решение о слиянии принимается на этой странице, а не в переписке:
263
- сказанное владельцу вслух живёт до следующей реплики, а тело лежит у самой кнопки. Одно другого
264
- не отменяет — порядок обоих сообщений владельцу описывает паттерн закрытия работы.
265
-
266
- Проверить тело машиной нечем: ни одна сверка его не читает, а хостинг спрашивает только про
267
- заголовок. Держится образец тем, кто пишет тело, — как и слова вслух.
268
-
269
- ## Состояние PR читается, а не додумывается
270
-
271
- Команды правки отвечают нулевым кодом и тогда, когда ничего не сделали. Поэтому после них PR
272
- перечитывают:
273
-
274
- ```bash
275
- az repos pr show --id 205 \
276
- --query '{author: createdBy.uniqueName, reviewers: reviewers[].uniqueName, work: workItemRefs[].id}'
277
- ```
278
-
279
- Владельцу называют то, что прочитали, а не то, что заказывали.
280
-
281
- Перечитывают его и по времени, а не только после вызовов, которые молча ничего не сделали:
282
- состояние PR читается перед тем, как что-либо о нём сказать. Между «прогон зелёный» и следующей
283
- фразой владелец успевает влить PR, и всё сказанное о нём после этого — про вчерашний день. Так
284
- владельцу и было предложено влить то, что он влил часом раньше.
285
-
286
- Открытый PR означает, что элемент ждёт разбора, — состояние переставляется тем же движением:
287
-
288
- ```bash
289
- npm run task:move -- 86 in-review
290
- ```
291
-
292
- ## Что проверяется до публикации PR
293
-
294
- Конвейер видит только отправленное, а отправляется оно пушем. Линтеры, юниты и сценарии хуков
295
- снимает гейт пуша — ниже то, чего он не знает.
296
-
297
- 1. **Главная ветка влита в эту ветку** — `git fetch origin && git merge origin/main`.
298
- Всё, что проверяется ниже, проверяется от этого основания: PR с разошедшейся ветки
299
- показывает ревьюверу правку вперемешку с чужой. Порядок и разбор конфликта — паттерн
300
- `git-workflow-merge`.
301
- 2. **В ветке только та правка, за которой её заводили** — `git diff main...HEAD --stat`. Чужой
302
- домен в списке файлов означает, что правка расползлась, и её надо вернуть в свои границы.
303
- 3. **Ни мока, ни подменённого ответа, ни отладочной строки** — `git diff main...HEAD` читается
304
- целиком, а не по именам файлов. На прод они уезжают молча и портят настоящие данные.
305
- 4. **Документ едет тем же коммитом.** Пару называет `docs-guard`, но спек домена и правку его
306
- поведения он не знает — это остаётся за автором.
307
- 5. **Проверки текстов и раскладки зелёные** — те, что дерево завело в `tools/`. Какие именно
308
- есть здесь — `implementation.md` правила.
309
- 6. **Все приложения дерева собираются** — `nx build` по каждому. Гейт пуша сборку не гоняет.
310
- 7. **Видимый текст заведён во всех локалях перевода** — тестом полноты словарей, если дерево
311
- переводится.
312
- 8. **Правка вёрстки подтверждена замером**, а не взглядом, и снята при узком экране — паттерн
313
- `browser-verification-measure`.
314
- 9. **Правка разметки публичного сайта проверена на прод-сборке по всем локалям перевода** —
315
- паттерн `seo-verify`.
316
- 10. **PR привязан к рабочему элементу**, ревьювер и исполнитель стоят, а тело собрано по
317
- образцу — разделы «Что сделано», «Чем подтверждено» и «Оставшийся шаг». Раздел оставшегося
318
- шага к этому моменту говорит, что шагов не осталось: черновик снимается после разбора
319
- папки, а не до него.
320
- 11. **Заголовок PR несёт номер элемента и называет работу сделанной:** `[<номер>] <Что
321
- сделано>`, тем же номером, что стоит у элемента и в имени ветки.
322
- 12. **Очередь работ сходится** — `npm run check:board`.
323
- 13. **Состояние PR прочитано, а не выведено из кодов возврата.**
324
- 14. **Набор взят из файла конвейера, а не собран по памяти.** Гейт пуша заведомо уже: он стоит
325
- между командой и пушем, и всё, что дольше секунд, из него вынесено. Что гоняет конвейер,
326
- написано в его файле — этот список и повторяется локально; зелёный гейт полнотой набора не
327
- является.
328
- 15. **Набор пересмотрен после вливания главной ветки.** Он выбирается по тому, что ветка везёт
329
- теперь, а не по тому, что правил автор. Ветка, не тронувшая ни строки показа, прогоняет
330
- снимки витрин: с момента вливания их гоняет конвейер на её коде, и красное придёт на её
331
- PR.
332
-
333
- Сразу после публикации элемент переводится в разбор, и сверка очереди прогоняется ещё раз: до
334
- открытия PR состояние она не судит, а после открытия расхождение видит.
335
-
336
- Сделанное рассуждением и сделанное замером в теле PR разводятся прямо: непроверенное,
337
- названное проверенным, ревьювер принимает за проверенное.
338
-
339
- **Раздел «Чем подтверждено» называет и то, что не гонялось.** Список одного прогнанного
340
- неотличим от полного набора, и ревьювер по нему решает, что можно не перепроверять. Цена ошибки
341
- здесь не красный конвейер, а доверие к разделу: однажды прочитанный как полнота, дальше он
342
- перепроверяется весь.
343
-
344
152
  ## Частые промахи
345
153
 
346
154
  - Область и итерация не заданы: элемент заведён, но на доску команды не попал.
347
155
  - Состояние взято не из процесса проекта: перевод отвечает отказом на каждой задаче, и это
348
156
  читается как сломанная команда, а не как неверное имя состояния.
349
- - PR открыт без `--work-items`: связи нет, и по очереди работ не видно, за чем эта правка.
350
- - `AB#<номер>` в коммите принят за привязку PR: он связывает коммит, а очередь читает связь PR.
351
157
  - `git add` с несколькими путями не добавляет ничего, если хоть один путь не существует:
352
158
  команда обрывается на первом промахе целиком. Следующий `git commit --amend` при этом уносит
353
159
  в коммит всё, что осталось в индексе. Состав коммита читается `git show --stat` сразу после
354
160
  него, а не на разборе PR.
355
- - PR открыт без ревьювера: он не попадает во входящие владельца, и очередь стоит, выглядя
356
- работающей.
357
- - `--delete-source-branch` забыт: ветки задач копятся в репозитории, и по списку веток больше
358
- не видно, какая работа идёт сейчас.
359
- - Автозавершение включено до того, как прогнаны проверки до пуша: конвейер зелёный на том, что
360
- он умеет, и слияние происходит без всего остального.
361
161
  - Правка владельца ни токена, ни переменных не берёт — они только для машинной работы.