@rt-tools/agent-kit 0.8.0 → 0.8.2
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.
- package/README.md +24 -19
- package/assets/agents/qa-engineer.md +1 -1
- package/assets/checks/board.github.mjs +56 -17
- package/assets/checks/check-board.github.mjs +49 -5
- package/assets/checks/check-reuse.mjs +9 -7
- package/assets/checks/task-new.github.mjs +33 -5
- package/assets/commands/agent-kit-digest.md +10 -5
- package/assets/commands/next-session.md +4 -4
- package/assets/commands/skill-curator.md +11 -9
- package/assets/defaults/gate-map.sh +11 -4
- package/assets/defaults/project.sh +46 -0
- package/assets/docs/GLOSSARY.md +28 -26
- package/assets/hooks/docs-guard.sh +19 -3
- package/assets/hooks/git-guard-delivery.sh +106 -13
- package/assets/hooks/proposal-guard.sh +93 -0
- package/assets/hooks/reuse-first-guard.sh +68 -14
- package/assets/hooks/skill-gate-layers.sh +1 -1
- package/assets/hooks/skill-gate.sh +26 -0
- package/assets/hooks/task-flow-guard.sh +44 -18
- package/assets/hooks/window-fill-guard.sh +1 -1
- package/assets/laws/delivery.md +13 -7
- package/assets/laws/project-documentation.md +21 -0
- package/assets/laws/verifiability.md +6 -1
- package/assets/laws/work-conduct.md +67 -3
- package/assets/patterns/git-workflow-commit.azure.md +10 -2
- package/assets/patterns/git-workflow-commit.github.md +15 -2
- package/assets/patterns/git-workflow-commit.gitlab.md +10 -2
- package/assets/patterns/git-workflow-merge.md +1 -1
- package/assets/patterns/reuse-first-extend.md +12 -3
- package/assets/patterns/spec-driven-domain.md +7 -1
- package/assets/patterns/spec-driven-rule.md +6 -0
- package/assets/patterns/task-flow-close.md +78 -9
- package/assets/patterns/task-flow-handoff.md +27 -4
- package/assets/patterns/task-flow-resume.md +23 -5
- package/assets/patterns/task-flow-start.md +5 -1
- package/assets/rules/browser-verification.md +10 -1
- package/assets/rules/doc-style.md +13 -5
- package/assets/rules/git-workflow.azure.md +12 -7
- package/assets/rules/git-workflow.github.md +31 -13
- package/assets/rules/git-workflow.gitlab.md +12 -7
- package/assets/rules/reuse-first.md +1 -1
- package/assets/rules/spec-driven.md +4 -0
- package/assets/rules/task-flow.md +47 -22
- package/assets/rules/testing.md +19 -0
- package/assets/rules/typescript-conventions.md +12 -0
- package/assets/skills/agent-kit-extend.md +173 -0
- package/assets/skills/agent-kit.md +62 -10
- package/assets/traits.json +14 -0
- package/bin/agent-kit.d.ts.map +1 -1
- package/bin/agent-kit.js +31 -16
- package/bin/agent-kit.js.map +1 -1
- package/index.d.ts +1 -0
- package/index.d.ts.map +1 -1
- package/index.js +1 -0
- package/index.js.map +1 -1
- package/lib/argv.d.ts +17 -0
- package/lib/argv.d.ts.map +1 -0
- package/lib/argv.js +44 -0
- package/lib/argv.js.map +1 -0
- package/lib/cargo.d.ts +88 -0
- package/lib/cargo.d.ts.map +1 -0
- package/lib/cargo.js +16 -0
- package/lib/cargo.js.map +1 -0
- package/lib/catalog.d.ts +18 -1
- package/lib/catalog.d.ts.map +1 -1
- package/lib/catalog.js +12 -2
- package/lib/catalog.js.map +1 -1
- package/lib/commands.d.ts +0 -26
- package/lib/commands.d.ts.map +1 -1
- package/lib/commands.js +78 -122
- package/lib/commands.js.map +1 -1
- package/lib/companion.d.ts +37 -0
- package/lib/companion.d.ts.map +1 -1
- package/lib/companion.js +42 -1
- package/lib/companion.js.map +1 -1
- package/lib/config.d.ts +28 -0
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js +20 -0
- package/lib/config.js.map +1 -1
- package/lib/ship.d.ts +39 -0
- package/lib/ship.d.ts.map +1 -0
- package/lib/ship.js +87 -0
- package/lib/ship.js.map +1 -0
- package/lib/shipment.d.ts +60 -0
- package/lib/shipment.d.ts.map +1 -0
- package/lib/shipment.js +247 -0
- package/lib/shipment.js.map +1 -0
- package/lib/snapshot.d.ts +30 -0
- package/lib/snapshot.d.ts.map +1 -0
- package/lib/snapshot.js +73 -0
- package/lib/snapshot.js.map +1 -0
- package/lib/traits.d.ts +32 -0
- package/lib/traits.d.ts.map +1 -0
- package/lib/traits.js +82 -0
- package/lib/traits.js.map +1 -0
- package/package.json +6 -2
- package/rt-tools-agent-kit-0.8.2.tgz +0 -0
- package/lib/submit.d.ts +0 -24
- package/lib/submit.d.ts.map +0 -1
- package/lib/submit.js +0 -26
- package/lib/submit.js.map +0 -1
- package/rt-tools-agent-kit-0.8.0.tgz +0 -0
- /package/assets/rules/{entity-conventions.md → entity-conventions.needs-admin.md} +0 -0
- /package/assets/rules/{observability.md → observability.needs-app.md} +0 -0
|
@@ -38,14 +38,46 @@ command -v jq >/dev/null 2>&1 || exit 0
|
|
|
38
38
|
command -v perl >/dev/null 2>&1 || exit 0
|
|
39
39
|
|
|
40
40
|
tool="$(printf '%s' "$input" | jq -r '.tool_name // empty' 2>/dev/null)"
|
|
41
|
+
shell_cmd=""
|
|
41
42
|
case "$tool" in
|
|
42
43
|
# Инструмент среды заводит файл теми же двумя данными, только называет их иначе — без этой
|
|
43
44
|
# ветки файл заводился мимо всех проверок.
|
|
44
45
|
Edit | Write | MultiEdit | mcp__webstorm__create_new_file) ;;
|
|
46
|
+
# Команда оболочки, которая пишет файл, — та же правка. Без этой ветки гард обходится
|
|
47
|
+
# сменой не инструмента, а способа записи; текстом правки тогда служит сама команда, и
|
|
48
|
+
# заведённое ею в heredoc читается наравне с телом правки. Разбор —
|
|
49
|
+
# `2026-08-15-guard-denied-shell-wrote-anyway.md`.
|
|
50
|
+
Bash)
|
|
51
|
+
shell_cmd="$(printf '%s' "$input" | jq -r '.tool_input.command // empty' 2>/dev/null)"
|
|
52
|
+
[ -z "$shell_cmd" ] && exit 0
|
|
53
|
+
;;
|
|
45
54
|
*) exit 0 ;;
|
|
46
55
|
esac
|
|
47
56
|
|
|
48
|
-
|
|
57
|
+
# Профиль дерева: сперва умолчание пакета, поверх него — надстройка проекта, если она есть.
|
|
58
|
+
# Читается до разбора пути: пути из команды оболочки вынимает как раз профиль.
|
|
59
|
+
rt_hooks_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
60
|
+
for profile in "$rt_hooks_dir/../rt-kit/defaults/project.sh" "$rt_hooks_dir/../defaults/project.sh" "${CLAUDE_PROJECT_DIR:-.}/.claude/rt-kit/defaults/project.sh" "${CLAUDE_PROJECT_DIR:-.}/.claude/rt-kit/project.sh"; do
|
|
61
|
+
# shellcheck disable=SC1090
|
|
62
|
+
[ -f "$profile" ] && . "$profile" 2>/dev/null
|
|
63
|
+
done
|
|
64
|
+
|
|
65
|
+
if [ -n "$shell_cmd" ]; then
|
|
66
|
+
command -v rt_shell_writes >/dev/null 2>&1 && command -v rt_shell_paths >/dev/null 2>&1 || exit 0
|
|
67
|
+
rt_shell_writes "$shell_cmd" || exit 0
|
|
68
|
+
# Из команды берётся первый путь, чьё расширение гарду интересно: остальные ему безразличны.
|
|
69
|
+
path=""
|
|
70
|
+
while IFS= read -r candidate; do
|
|
71
|
+
case "$candidate" in
|
|
72
|
+
*.html | *.scss | *.ts) path="$candidate"; break ;;
|
|
73
|
+
esac
|
|
74
|
+
done <<EOF
|
|
75
|
+
$(rt_shell_paths "$shell_cmd")
|
|
76
|
+
EOF
|
|
77
|
+
[ -z "$path" ] && exit 0
|
|
78
|
+
else
|
|
79
|
+
path="$(printf '%s' "$input" | jq -r '.tool_input.file_path // .tool_input.pathInProject // empty' 2>/dev/null)"
|
|
80
|
+
fi
|
|
49
81
|
# Путь от корня дерева приводится к абсолютному один раз, чтобы образцы не двоились.
|
|
50
82
|
case "$path" in
|
|
51
83
|
/*) ;;
|
|
@@ -56,13 +88,6 @@ case "$path" in
|
|
|
56
88
|
*) exit 0 ;;
|
|
57
89
|
esac
|
|
58
90
|
|
|
59
|
-
# Профиль дерева: сперва умолчание пакета, поверх него — надстройка проекта, если она есть.
|
|
60
|
-
rt_hooks_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
61
|
-
for profile in "$rt_hooks_dir/../rt-kit/defaults/project.sh" "$rt_hooks_dir/../defaults/project.sh" "${CLAUDE_PROJECT_DIR:-.}/.claude/rt-kit/defaults/project.sh" "${CLAUDE_PROJECT_DIR:-.}/.claude/rt-kit/project.sh"; do
|
|
62
|
-
# shellcheck disable=SC1090
|
|
63
|
-
[ -f "$profile" ] && . "$profile" 2>/dev/null
|
|
64
|
-
done
|
|
65
|
-
|
|
66
91
|
# Слово о нехватке функции профиля: хук, вышедший молча, неотличим от работающего. Файл может
|
|
67
92
|
# быть не разложен — тогда остаётся прежнее поведение, молчаливое.
|
|
68
93
|
# shellcheck disable=SC1090
|
|
@@ -82,11 +107,16 @@ if [ -n "${RT_REUSE_SKIP_RE:-}" ] && printf '%s' "$path" | grep -qE "$RT_REUSE_S
|
|
|
82
107
|
exit 0
|
|
83
108
|
fi
|
|
84
109
|
|
|
85
|
-
# Только новый текст: строка, уже лежавшая в файле, этой правкой не заводилась.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
110
|
+
# Только новый текст: строка, уже лежавшая в файле, этой правкой не заводилась. У команды
|
|
111
|
+
# оболочки таким текстом служит она сама: что она кладёт в файл, лежит в ней же.
|
|
112
|
+
if [ -n "$shell_cmd" ]; then
|
|
113
|
+
added="$shell_cmd"
|
|
114
|
+
else
|
|
115
|
+
added="$(printf '%s' "$input" | jq -r '
|
|
116
|
+
[ .tool_input.content?, .tool_input.text?, .tool_input.new_string?, (.tool_input.edits[]?.new_string) ]
|
|
117
|
+
| map(select(. != null)) | join("\n")
|
|
118
|
+
' 2>/dev/null)"
|
|
119
|
+
fi
|
|
90
120
|
[ -z "$added" ] && exit 0
|
|
91
121
|
|
|
92
122
|
# Явный отказ от правила: готового такого нет, автор это осознал и пометил. Считается по
|
|
@@ -138,11 +168,19 @@ has_re() {
|
|
|
138
168
|
rt_checks_json="${CLAUDE_PROJECT_DIR:-.}/.claude/rt-kit/checks.json"
|
|
139
169
|
rt_bundles=''
|
|
140
170
|
rt_own_signals=''
|
|
171
|
+
rt_backend_roots=''
|
|
141
172
|
if [ -f "$rt_checks_json" ]; then
|
|
142
173
|
rt_bundles="$(jq -r '.reuse.bundles[]? // empty' "$rt_checks_json" 2>/dev/null | tr '\n' ' ')"
|
|
143
174
|
own="$(jq -r '.reuse.signals // empty' "$rt_checks_json" 2>/dev/null)"
|
|
144
175
|
[ -n "$own" ] && rt_own_signals="${CLAUDE_PROJECT_DIR:-.}/$own"
|
|
176
|
+
# Тем же ключом, каким их читает сплошная проверка: второе объявление тех же корней
|
|
177
|
+
# разошлось бы с первым молча.
|
|
178
|
+
rt_backend_roots="$(jq -r '.backendRoots[]? // empty' "$rt_checks_json" 2>/dev/null | tr '\n' ' ')"
|
|
145
179
|
fi
|
|
180
|
+
|
|
181
|
+
# Путь от корня дерева: образец в признаке пишет дерево, и писать его от корня машины оно не
|
|
182
|
+
# может. Абсолютный путь нужен только для чтения файла с диска.
|
|
183
|
+
rel_path="${path#"${CLAUDE_PROJECT_DIR:-.}"/}"
|
|
146
184
|
rt_signals_dir="${CLAUDE_PROJECT_DIR:-.}/${RT_REUSE_SIGNALS_DIR:-tools/signals}"
|
|
147
185
|
|
|
148
186
|
# Признаки объявленных наборов: те же файлы читает сплошная проверка. Ключ признака совпал с
|
|
@@ -172,9 +210,25 @@ while IFS= read -r signal; do
|
|
|
172
210
|
'') ;;
|
|
173
211
|
*) case "$path" in *"$ext") ;; *) continue ;; esac ;;
|
|
174
212
|
esac
|
|
213
|
+
# Пропуск корней бэкенда: признак, объявленный с ним, на бэкенде не действует вовсе — там
|
|
214
|
+
# принят другой способ, и базового класса, которого признак требует, у бэкенда нет. Поле
|
|
215
|
+
# читает и сплошная проверка; читать его одному из двоих значит отбивать гардом ту самую
|
|
216
|
+
# правку, которую проверка пропускает, — а провести её больше нечем: маркер отступления
|
|
217
|
+
# объявляет обход готового, а обхода тут не было.
|
|
218
|
+
if [ "$(field "$signal" '.skipBackendRoots')" = 'true' ] && [ -n "$rt_backend_roots" ]; then
|
|
219
|
+
skip_backend=''
|
|
220
|
+
for backend_root in $rt_backend_roots; do
|
|
221
|
+
case "$rel_path" in "$backend_root"*) skip_backend=1 ;; esac
|
|
222
|
+
done
|
|
223
|
+
[ -n "$skip_backend" ] && continue
|
|
224
|
+
fi
|
|
225
|
+
|
|
226
|
+
# Образец имени сверяется с путём от корня дерева, а не с именем файла: слои, которые
|
|
227
|
+
# признак и разделяет, зовут свои файлы одинаково, и по имени они неразличимы. Сплошная
|
|
228
|
+
# проверка сверяет с путём — расходиться им нельзя.
|
|
175
229
|
only_named="$(field "$signal" '.onlyNamed')"
|
|
176
230
|
if [ -n "$only_named" ]; then
|
|
177
|
-
printf '%s' "$
|
|
231
|
+
printf '%s' "$rel_path" | grep -qE "$only_named" || continue
|
|
178
232
|
fi
|
|
179
233
|
|
|
180
234
|
case "$(field "$signal" '.scope')" in
|
|
@@ -124,7 +124,7 @@ esac
|
|
|
124
124
|
|
|
125
125
|
# --- слой по пути: ведение работы -------------------------------------------------------------
|
|
126
126
|
#
|
|
127
|
-
# Папка задачи, договорённость о продукте до кода и
|
|
127
|
+
# Папка задачи, договорённость о продукте до кода и замысел эпика — первые файлы, которые
|
|
128
128
|
# заводятся в работе. Требование ловит на них того, кто пошёл мимо порядка: «пришла новая
|
|
129
129
|
# задача» инструментом не является, и поймать это больше нечем.
|
|
130
130
|
case "$target" in
|
|
@@ -90,6 +90,32 @@ case "$tool" in
|
|
|
90
90
|
fi
|
|
91
91
|
req="$(skill_for bash "$target" "" 2>/dev/null)"
|
|
92
92
|
kind="command"
|
|
93
|
+
# Команда оболочки, которая пишет файл, — та же правка, и правило ей нужно то же.
|
|
94
|
+
# Без этого яруса гейт обходится сменой не инструмента, а способа записи: отбитая
|
|
95
|
+
# правка легла командой дважды за один заход. Разбор —
|
|
96
|
+
# `2026-08-15-guard-denied-shell-wrote-anyway.md`.
|
|
97
|
+
for profile in "$rt_hooks_dir/../rt-kit/defaults/project.sh" "$rt_hooks_dir/../defaults/project.sh" "${CLAUDE_PROJECT_DIR:-.}/.claude/rt-kit/defaults/project.sh" "${CLAUDE_PROJECT_DIR:-.}/.claude/rt-kit/project.sh"; do
|
|
98
|
+
# shellcheck disable=SC1090
|
|
99
|
+
[ -f "$profile" ] && . "$profile" 2>/dev/null
|
|
100
|
+
done
|
|
101
|
+
if command -v rt_shell_writes >/dev/null 2>&1 && command -v rt_shell_paths >/dev/null 2>&1 \
|
|
102
|
+
&& rt_shell_writes "$target"; then
|
|
103
|
+
while IFS= read -r written_path; do
|
|
104
|
+
[ -z "$written_path" ] && continue
|
|
105
|
+
case "$written_path" in
|
|
106
|
+
/*) ;;
|
|
107
|
+
*) written_path="${CLAUDE_PROJECT_DIR:-.}/$written_path" ;;
|
|
108
|
+
esac
|
|
109
|
+
case "$written_path" in
|
|
110
|
+
"${CLAUDE_PROJECT_DIR:-.}"/*) ;;
|
|
111
|
+
*) continue ;;
|
|
112
|
+
esac
|
|
113
|
+
more="$(skill_for edit "$written_path" "" 2>/dev/null)"
|
|
114
|
+
[ -n "$more" ] && req="$req $more"
|
|
115
|
+
done <<EOF
|
|
116
|
+
$(rt_shell_paths "$target")
|
|
117
|
+
EOF
|
|
118
|
+
fi
|
|
93
119
|
;;
|
|
94
120
|
mcp__claude-in-chrome__*)
|
|
95
121
|
req="$(skill_for browser "$tool" "" 2>/dev/null)"
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
#
|
|
6
6
|
# Работа идёт много заходов, и между ними исполнитель не помнит ничего. Замысел, лежащий на
|
|
7
7
|
# диске, — единственное, что переживает перерыв: изменения к этому моменту бывают не
|
|
8
|
-
# закоммичены,
|
|
8
|
+
# закоммичены, PR не открыт, а очередь работ показывает задачу начатой и молчит о том, что
|
|
9
9
|
# внутри неё сделано.
|
|
10
10
|
#
|
|
11
11
|
# Гард требует три вещи и ровно их: папку задачи по имени ветки, замысел в ней и названную в
|
|
@@ -24,22 +24,8 @@ input="$(cat 2>/dev/null)"
|
|
|
24
24
|
[ -z "$input" ] && exit 0
|
|
25
25
|
command -v jq >/dev/null 2>&1 || exit 0
|
|
26
26
|
|
|
27
|
-
tool="$(printf '%s' "$input" | jq -r '.tool_name // empty' 2>/dev/null)"
|
|
28
|
-
case "$tool" in
|
|
29
|
-
# Инструмент редактора заводит файл теми же двумя данными, только называет их иначе —
|
|
30
|
-
# без этой ветки правка шла бы мимо гарда сменой инструмента.
|
|
31
|
-
Edit | Write | MultiEdit | mcp__webstorm__create_new_file) ;;
|
|
32
|
-
*) exit 0 ;;
|
|
33
|
-
esac
|
|
34
|
-
|
|
35
|
-
path="$(printf '%s' "$input" | jq -r '.tool_input.file_path // .tool_input.pathInProject // empty' 2>/dev/null)"
|
|
36
|
-
[ -z "$path" ] && exit 0
|
|
37
|
-
case "$path" in
|
|
38
|
-
/*) ;;
|
|
39
|
-
?*) path="${CLAUDE_PROJECT_DIR:-.}/$path" ;;
|
|
40
|
-
esac
|
|
41
|
-
|
|
42
27
|
# Профиль дерева: сперва умолчание пакета, поверх него — надстройка проекта, если она есть.
|
|
28
|
+
# Читается до разбора пути: пути из команды оболочки вынимает как раз профиль.
|
|
43
29
|
rt_hooks_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
44
30
|
for profile in "$rt_hooks_dir/../rt-kit/defaults/project.sh" "$rt_hooks_dir/../defaults/project.sh" "${CLAUDE_PROJECT_DIR:-.}/.claude/rt-kit/defaults/project.sh" "${CLAUDE_PROJECT_DIR:-.}/.claude/rt-kit/project.sh"; do
|
|
45
31
|
# shellcheck disable=SC1090
|
|
@@ -52,12 +38,52 @@ done
|
|
|
52
38
|
[ -f "$rt_hooks_dir/profile-check.sh" ] && . "$rt_hooks_dir/profile-check.sh"
|
|
53
39
|
command -v rt_needs >/dev/null 2>&1 || rt_needs() { command -v "$1" >/dev/null 2>&1; }
|
|
54
40
|
|
|
41
|
+
tool="$(printf '%s' "$input" | jq -r '.tool_name // empty' 2>/dev/null)"
|
|
42
|
+
candidates=""
|
|
43
|
+
case "$tool" in
|
|
44
|
+
# Инструмент редактора заводит файл теми же двумя данными, только называет их иначе —
|
|
45
|
+
# без этой ветки правка шла бы мимо гарда сменой инструмента.
|
|
46
|
+
Edit | Write | MultiEdit | mcp__webstorm__create_new_file)
|
|
47
|
+
candidates="$(printf '%s' "$input" | jq -r '.tool_input.file_path // .tool_input.pathInProject // empty' 2>/dev/null)"
|
|
48
|
+
;;
|
|
49
|
+
# Второй ярус: та же правка, положенная командой оболочки. Без него отказ гарда обходится
|
|
50
|
+
# сменой не инструмента, а способа записи — перенаправлением, `sed -i`, интерпретатором с
|
|
51
|
+
# heredoc. Разбор — `2026-08-15-guard-denied-shell-wrote-anyway.md`.
|
|
52
|
+
Bash)
|
|
53
|
+
cmd="$(printf '%s' "$input" | jq -r '.tool_input.command // empty' 2>/dev/null)"
|
|
54
|
+
[ -z "$cmd" ] && exit 0
|
|
55
|
+
rt_needs rt_shell_writes task-flow-guard || exit 0
|
|
56
|
+
rt_needs rt_shell_paths task-flow-guard || exit 0
|
|
57
|
+
rt_shell_writes "$cmd" || exit 0
|
|
58
|
+
candidates="$(rt_shell_paths "$cmd")"
|
|
59
|
+
;;
|
|
60
|
+
*) exit 0 ;;
|
|
61
|
+
esac
|
|
62
|
+
[ -z "$candidates" ] && exit 0
|
|
63
|
+
|
|
55
64
|
# Признак «правка меняет поведение» — путь, а не оценка на глаз: оценку назначает тот, кому
|
|
56
65
|
# она мешает, и порог плывёт. Где живёт код приложения, знает профиль: правила, тексты, обвязка
|
|
57
66
|
# и зависимости под требование не попадают — иначе разбор задачи нельзя было бы вести до
|
|
58
67
|
# заведения ветки.
|
|
59
68
|
rt_needs rt_is_app_code task-flow-guard || exit 0
|
|
60
|
-
|
|
69
|
+
|
|
70
|
+
# Судится каждый названный путь: команда пишет столько файлов, сколько в ней стоит, и одного
|
|
71
|
+
# под требованием довольно, чтобы отбить её целиком.
|
|
72
|
+
path=""
|
|
73
|
+
while IFS= read -r candidate; do
|
|
74
|
+
[ -z "$candidate" ] && continue
|
|
75
|
+
case "$candidate" in
|
|
76
|
+
/*) ;;
|
|
77
|
+
*) candidate="${CLAUDE_PROJECT_DIR:-.}/$candidate" ;;
|
|
78
|
+
esac
|
|
79
|
+
if rt_is_app_code "$candidate"; then
|
|
80
|
+
path="$candidate"
|
|
81
|
+
break
|
|
82
|
+
fi
|
|
83
|
+
done <<EOF
|
|
84
|
+
$candidates
|
|
85
|
+
EOF
|
|
86
|
+
[ -z "$path" ] && exit 0
|
|
61
87
|
|
|
62
88
|
# Каталог папок задач: у дерева он свой, но имя обычно общее.
|
|
63
89
|
tasks_dir="${RT_TASKS_DIR:-docs/tasks}"
|
|
@@ -113,7 +139,7 @@ fi
|
|
|
113
139
|
|
|
114
140
|
# Договорённость, влитая в спек домена, с диска уходит — так и задумано: в главной ветке
|
|
115
141
|
# директории «предложено» быть не должно. Но замысел на неё ссылается до конца работы, и без
|
|
116
|
-
# этой развилки последний коммит
|
|
142
|
+
# этой развилки последний коммит PR запирал бы ветку: ни правки по замечаниям разбора, ни
|
|
117
143
|
# записи в журнал изменений после вливания уже не сделать.
|
|
118
144
|
#
|
|
119
145
|
# Влитое от незаведённого отличает история ветки: путь, которого в ней никогда не было,
|
|
@@ -131,7 +131,7 @@ case "$tool" in
|
|
|
131
131
|
esac
|
|
132
132
|
;;
|
|
133
133
|
Bash | mcp__webstorm__execute_terminal_command)
|
|
134
|
-
# Поставка и сверки: коммит, пуш,
|
|
134
|
+
# Поставка и сверки: коммит, пуш, PR, колонка задачи, состояние дерева. Список
|
|
135
135
|
# дописывается профилем дерева — клиент хостинга и имена команд у каждого свои.
|
|
136
136
|
if rt_needs rt_handoff_allowed_cmd window-fill-guard && rt_handoff_allowed_cmd "$cmd"; then
|
|
137
137
|
allowed=1
|
package/assets/laws/delivery.md
CHANGED
|
@@ -28,10 +28,10 @@
|
|
|
28
28
|
своим номером, а то, чего в первой не было, дописывается в неё до этого. Две строки об
|
|
29
29
|
одной работе хуже дыры в нумерации: по ним потом не понять, что сделано, а что нет. Слить
|
|
30
30
|
их можно, пока правка не въехала в главную ветку; после — обе остаются как есть.
|
|
31
|
-
- **Задача, ветка под неё и
|
|
31
|
+
- **Задача, ветка под неё и PR о сделанном несут один и тот же номер в своих названиях.**
|
|
32
32
|
Иначе одну работу приходится узнавать по тексту названия, а в списке из полусотни строк это
|
|
33
33
|
делается по памяти и с ошибками.
|
|
34
|
-
- **Номер пишется всюду одинаково: ключ задач, дефис, номер.** Заголовок задачи и
|
|
34
|
+
- **Номер пишется всюду одинаково: ключ задач, дефис, номер.** Заголовок задачи и PR
|
|
35
35
|
начинается с этой пары в квадратных скобках, имя ветки — с неё же. Одна форма, а не три
|
|
36
36
|
похожих, потому что номер читают не только глазами: из имени ветки его достаёт гард, из
|
|
37
37
|
заголовка — сверка очереди. Формы, выведенные порознь, расходятся молча и не отказывают, а
|
|
@@ -46,9 +46,9 @@
|
|
|
46
46
|
ничьей: по очереди работ не видно, кто её взял, и заведённая по ходу правка теряется среди
|
|
47
47
|
чужих.
|
|
48
48
|
- **Состояние задачи в очереди работ отвечает тому, что с ней происходит.** Взятая в работу
|
|
49
|
-
видна взятой, а та,
|
|
49
|
+
видна взятой, а та, PR по которой ждёт разбора, — ждущей разбора. Иначе очередь показывает
|
|
50
50
|
один и тот же вид у нетронутого, у делаемого прямо сейчас и у сделанного: работа берётся
|
|
51
|
-
второй раз, а
|
|
51
|
+
второй раз, а PR стоит неразобранным, пока про него не вспомнят. Состояние переставляется
|
|
52
52
|
в тот момент, когда работа переходит на следующий шаг, а не приводится в порядок потом:
|
|
53
53
|
очередь читают между этими моментами, а не после них.
|
|
54
54
|
- **Попадание правки в главную ветку означает выкатку.** Всё, от чего правка зависит снаружи
|
|
@@ -71,10 +71,16 @@
|
|
|
71
71
|
иначе «сошлось» значит в этих двух местах разное.
|
|
72
72
|
- **Документ едет вместе с правкой, которую он описывает.** Ни сборка, ни проверки текстов
|
|
73
73
|
не читают, поэтому расхождение копится молча и потом выглядит действующей справкой.
|
|
74
|
-
-
|
|
74
|
+
- **PR о сделанном остаётся верным до самого слияния.** Он описывает дерево на день, когда
|
|
75
75
|
его написали, а разбора ждёт днями: за это время главная ветка вливается в ветку, и
|
|
76
|
-
утверждение
|
|
77
|
-
одна проверка. Всё, что вливается в ветку после публикации
|
|
76
|
+
утверждение PR о соседних файлах становится неправдой молча — тел PR не читает ни
|
|
77
|
+
одна проверка. Всё, что вливается в ветку после публикации PR, — повод перечитать его.
|
|
78
|
+
- **PR в главную ветку вливает человек.** Слияние — последний момент, когда разбор ещё
|
|
79
|
+
возможен: после него правка стоит в главной ветке, работа ушла к следующей задаче, и
|
|
80
|
+
вернуться к ней уже некому. Исполнитель работы вливает свой PR только по прямому слову
|
|
81
|
+
человека и только про названный PR; молчание разрешением не бывает, а слово, сказанное об
|
|
82
|
+
одном PR, на следующий не переносится. Иначе разбор проходит тот, кого разбирают, и
|
|
83
|
+
очередь PR выглядит разобранной, не будучи ею.
|
|
78
84
|
- **Слияние в главную ветку ещё не означает, что правка доехала.** Отказ выкатки не трогает ни
|
|
79
85
|
задачу, ни очередь работ, поэтому расхождение главной ветки с тем, что работает, обязано быть
|
|
80
86
|
видно там, где очередь читают. Иначе следующие работы вливаются поверх поломки, которую не
|
|
@@ -56,3 +56,24 @@
|
|
|
56
56
|
знает само дерево, а не текст, приехавший в него. Утверждение, сказанное безусловно, врёт тем
|
|
57
57
|
увереннее, что печатает его сам инструмент, — и поправить его дерево не может, если правки на
|
|
58
58
|
месте у такого текста не предусмотрено.
|
|
59
|
+
- **Принятое решение становится пунктом слоя правил, а не записью о прошлом.** Записанное
|
|
60
|
+
описанием прошлого перестаёт действовать в тот же день: описания прошлого не приходят в
|
|
61
|
+
контекст работы, читаются как история и ничего не требуют. Следующая работа принимает то же
|
|
62
|
+
решение заново — и принимает иначе, потому что доводов первого уже не видит.
|
|
63
|
+
- **У решения есть слой, и он выбирается по тому, о чём решение говорит.** Что должно быть
|
|
64
|
+
верно в продукте — статья закона. Каким приёмом это делается здесь — пункт правила. Готовый
|
|
65
|
+
код и порядок действий — паттерн. Решение, положенное не в свой слой, находится только тем,
|
|
66
|
+
кто уже знает, что оно есть.
|
|
67
|
+
- **Описание прошлого объясняет состоявшийся переезд, а не держит действующее требование.**
|
|
68
|
+
Разница видна вопросом: перестанет ли текст быть верным, если завтра всё переделать. Рассказ
|
|
69
|
+
о том, как и почему однажды перенесли, — прошлое; требование «делай так» — нет, и место ему
|
|
70
|
+
в слое правил.
|
|
71
|
+
- **Признак, по которому решение относят к прошлому, записан заранее и один на все работы.**
|
|
72
|
+
Выводимый каждой работой заново, он назначается тем, кому мешает: под конец работы дешевле
|
|
73
|
+
назвать прошлым всё, что осталось разобрать.
|
|
74
|
+
- **Раздел решений в описании домена — временное место, а не постоянное.** Пока решение там,
|
|
75
|
+
оно действует только для того, кто открыл этот файл. Разросшийся раздел — признак того, что
|
|
76
|
+
правило под него не заведено, а не того, что домен сложный.
|
|
77
|
+
- **Работа, которая переносит решения, называет для каждого, куда оно ушло.** Иначе по
|
|
78
|
+
описанию прошлого не отличить решение, ставшее правилом, от решения, потерянного при
|
|
79
|
+
переносе: оба выглядят одинаково — записью, на которую никто не ссылается.
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
- **Успешный ответ команды означает, что она отработала, а не что нужное состояние
|
|
34
34
|
наступило.** Часть запросов выполняется наполовину, и об отклонённой части в ответе ничего
|
|
35
35
|
нет: по коду возврата такой вызов не отличить от исполненного. Поэтому результат читают
|
|
36
|
-
отдельным запросом, и в
|
|
36
|
+
отдельным запросом, и в PR идёт то, что прочитали, а не то, что заказывали.
|
|
37
37
|
- **Служба считается поднятой, когда она выполнила задание, а не когда сообщила о
|
|
38
38
|
готовности.** Сообщение о готовности говорит лишь, что служба себя объявила: та, которой не
|
|
39
39
|
досталось ни одного задания, выглядит в нём точно так же, как работающая. Проверяются обе
|
|
@@ -47,6 +47,11 @@
|
|
|
47
47
|
выключают в настройке инструмента, а не обходят в каждом месте.** Обход приходится повторять
|
|
48
48
|
столько раз, сколько таких мест, и ни в одном из них не написано, зачем он: со стороны это
|
|
49
49
|
выглядит ошибкой автора, а не решением.
|
|
50
|
+
- **Красная проверка означает неверный код, а не неверную проверку.** Место, выведенное
|
|
51
|
+
из-под проверки затем, чтобы она замолчала, чинит показание, а не то, на что она указала:
|
|
52
|
+
код остаётся прежним, а сигнала о нём больше нет ни у кого. Список известного накоплен к
|
|
53
|
+
дню заведения проверки и только сокращается; несогласие с самой проверкой — вопрос к
|
|
54
|
+
владельцу, а не строка в списке.
|
|
50
55
|
- **Польза правила подтверждается наблюдением за тем, как им пользуются, а не мнением о нём.**
|
|
51
56
|
Правило, которого не открыли ни разу, и правило, на котором держится половина работы, в тексте
|
|
52
57
|
выглядят одинаково — и правится первым обычно то, о чём вспомнили, а не то, что мешает.
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
- **Остановка называется первой строкой.** Сообщение, которым исполнитель останавливается,
|
|
21
21
|
начинается с того, чего он ждёт и что будет, если ответа не будет. Замеры, находки и разбор
|
|
22
22
|
к этому моменту уже записаны в ход работы — в сообщении владельцу они лишние. Чем подробнее
|
|
23
|
-
|
|
23
|
+
PR, тем надёжнее вопрос в нём тонет, и владелец переспрашивает, почему работа стоит.
|
|
24
24
|
- **Владельцу не задаётся вопрос, ответ на который уже записан.** Записанное читают до
|
|
25
25
|
разговора, а не вместо ответа: вопрос о том, что уже решено, обесценивает и остальные.
|
|
26
26
|
- **Вопрос владельцу задаётся после того, как ответ искали в дереве.** Что лежит в дереве,
|
|
@@ -31,6 +31,11 @@
|
|
|
31
31
|
«здесь нет», «этого не заводили», «такого файла не бывает» — произносится только как вывод
|
|
32
32
|
команды. Не проверенное отрицание опаснее вопроса: вопрос владелец поправит, а факт от
|
|
33
33
|
исполнителя примет на веру, потому что тот в дерево смотрит.
|
|
34
|
+
- **Отрицание, полученное одним источником, отрицанием не является.** Ответ «не найдено», отказ
|
|
35
|
+
в доступе и пустой список говорят о правах спрашивающего, а не о предмете: тот же вопрос,
|
|
36
|
+
заданный оттуда, где предмет виден, отвечает обратным. Сказать «этого нет» можно только после
|
|
37
|
+
второго источника — иначе исполнитель называет владельцу собственные права, приняв их за
|
|
38
|
+
устройство мира.
|
|
34
39
|
- **Решение, однажды записанное, действует, пока его не отменили, и читается до того, как
|
|
35
40
|
принимается заново.** Отменённое решение следа в работе не оставляет — по результату не
|
|
36
41
|
видно ни того, что его принимали, ни того, что от него отказались. Принятое заново оно
|
|
@@ -58,7 +63,7 @@
|
|
|
58
63
|
пересказ он даёт по своей памяти, а не по ходу работы, и следующий заход начинает с чужой
|
|
59
64
|
картины.
|
|
60
65
|
- **Замысел и ход работы — разные записи.** Замысел — то, с чем сверяют результат при
|
|
61
|
-
приёмке; правленный по ходу, он перестаёт отличаться от
|
|
66
|
+
приёмке; правленный по ходу, он перестаёт отличаться от PR, и приёмке сверять нечего.
|
|
62
67
|
- **Сделанное отмечается в одном месте.** Две записи об одном разъезжаются молча, и после
|
|
63
68
|
этого ни по одной не видно, что осталось.
|
|
64
69
|
- **Решение, принятое по ходу работы, записывается вместе с причиной.** Без причины оно
|
|
@@ -66,7 +71,7 @@
|
|
|
66
71
|
- **Граница работы названа до её начала.** Не названная вслух граница не существует: правка
|
|
67
72
|
расползается на соседнее, и снимать её приходится вручную.
|
|
68
73
|
- **Действия, которые исполнитель не делает сам, названы списком.** Всё, что уходит за
|
|
69
|
-
пределы рабочего дерева или не откатывается — запись в общий репозиторий, публикация,
|
|
74
|
+
пределы рабочего дерева или не откатывается — запись в общий репозиторий, публикация, PR,
|
|
70
75
|
правка общего документа, — делается по слову владельца, и слово это даётся на действие, а не
|
|
71
76
|
на работу целиком. Не названная списком граница выводится из общих слов: «делай, что нужно
|
|
72
77
|
по плану» прочитывается как разрешение на всё, что в плане подразумевалось.
|
|
@@ -104,3 +109,62 @@
|
|
|
104
109
|
- **У предложенной правки правил назван адрес: сам слой правил, имена этого дерева или его
|
|
105
110
|
надстройка.** Без адреса правку кладут туда, где она видна автору, — то есть в своё дерево, —
|
|
106
111
|
и общее оседает в одном месте, оставаясь неизвестным всем остальным.
|
|
112
|
+
- **Предложение, о котором владелец сказал вслух, уходит наружу в тот же ход.** Написанное и не
|
|
113
|
+
отправленное лежит в дереве неотличимо от отправленного: своей записи в слое правил у него
|
|
114
|
+
нет, и владелец читает работу сделанной, пока не спросит прямо. Слово владельца о предложении
|
|
115
|
+
— «отправь», «заведи», «напиши» — распоряжение, а не тема разговора; показ того, что уехало
|
|
116
|
+
бы, отправкой не является и следа наружу не оставляет.
|
|
117
|
+
- **Неудобство отправки — повод сказать о нём, а не повод не отправить.** Довод исполнителя
|
|
118
|
+
против уже принятого решения владельца остаётся доводом: он называется вслух, работа при этом
|
|
119
|
+
идёт. Отложить исполненное решение может только владелец; отложенное собственным доводом
|
|
120
|
+
выглядит для него сделанным, и цену этого он узнаёт последним.
|
|
121
|
+
- **Работа, из которой видно серию задач, объявляется эпиком до первой из них.** Объявляется
|
|
122
|
+
дважды: карточкой в очереди работ и замыслом рядом с ней. Не объявленная серия существует
|
|
123
|
+
только в голове того, кто её задумал: следующий заход видит разрозненные задачи, порядка между
|
|
124
|
+
ними не находит и берёт ту, что ближе лежит.
|
|
125
|
+
- **Замысел эпика называет разрабатываемую возможность, состав задач и их порядок.** Состав без
|
|
126
|
+
порядка порядком не является: две задачи, у которых порядок держался пониманием, ушли в работу
|
|
127
|
+
наоборот, и вторая переделывалась под первую. Возможность, названная одним словом, через неделю
|
|
128
|
+
читается каждым по-своему.
|
|
129
|
+
- **Порядок задач эпика назначается на планировании и держится до его конца.** Пересмотр по ходу
|
|
130
|
+
— решение владельца, записанное там же, где идёт работа. Порядок, назначаемый заново перед
|
|
131
|
+
каждой задачей, назначает тот, кому ближе, и эпик кончается там, где надоел.
|
|
132
|
+
- **Заход исполнителя не кончается вместе с задачей.** Конец задачи — не признак остановки:
|
|
133
|
+
остановиться позволяет только предел заполнения окна. Заход, закрытый на готовой задаче,
|
|
134
|
+
оставляет владельцу пустое место и стоит целого захода на возвращение к тому, что и так было
|
|
135
|
+
под рукой.
|
|
136
|
+
- **Работа, отданная на разбор, освобождает исполнителя, а не останавливает его.** Отданное на
|
|
137
|
+
разбор ждёт владельца, а не машину: следующая задача эпика берётся тем же движением, которым
|
|
138
|
+
предыдущая ушла на разбор.
|
|
139
|
+
- **Отдав работу на разбор, исполнитель называет, чего ждёт и что сделает следом.** Владелец
|
|
140
|
+
видит не голову исполнителя, а страницу работы: зелёная проверка и доступное действие
|
|
141
|
+
читаются как «всё кончено». Названное вслух ожидание — единственное, что отличает «жду
|
|
142
|
+
проверок, потом уберу за собой» от «готово, забирай». Не названное, оно не существует, и
|
|
143
|
+
владелец действует по тому, что видит.
|
|
144
|
+
- **Работа не считается готовой, пока исполнитель не сказал этого прямо.** Готовность объявляет
|
|
145
|
+
тот, кто работу вёл, — отдельной просьбой и про эту работу. Зелёные проверки готовностью не
|
|
146
|
+
являются: они говорят, что не сломано, и молчат о том, осталось ли что-то сделать. Молчание
|
|
147
|
+
исполнителя владелец читает как готовность, и между двумя прочтениями теряется всё, что
|
|
148
|
+
стояло после разбора.
|
|
149
|
+
- **Уборка за работой идёт до того, как о готовности сказано.** Всё, что работа обязана убрать
|
|
150
|
+
за собой, убирается раньше просьбы включить её в общее дерево, а не после согласия. После
|
|
151
|
+
включения убирать уже некому: работа перешла к следующей задаче.
|
|
152
|
+
- **Пока эпик не кончился, следующая работа не выбирается, а берётся.** Выбор, предложенный
|
|
153
|
+
владельцу при назначенном порядке, — это просьба назначить его заново: он уже назначен, и
|
|
154
|
+
предлагать его повторно значит отменять собственное планирование.
|
|
155
|
+
- **Замеченное по ходу и к эпику не относящееся становится задачей в очереди работ, а не работой
|
|
156
|
+
сейчас.** Отвлечение выглядит дешёвым ровно до того, как окажется, что вместе с ним уехала
|
|
157
|
+
правка соседнего домена: эпик при этом стоит, а откатывать приходится обе работы.
|
|
158
|
+
- **Эпик кончается, когда кончились его задачи, а не когда стало непонятно, что дальше.**
|
|
159
|
+
Непонятно бывает от того, что замысел не открыли: он лежит и держит решения, которых в коде не
|
|
160
|
+
видно.
|
|
161
|
+
- **Положение эпика показывается владельцу таблицей — в передаче и при остановке за его
|
|
162
|
+
решением.** Это два момента, когда владелец смотрит на работу снаружи: в первый он забирает её
|
|
163
|
+
в новый заход, во второй решает, куда её вести. Порядок задач при этом лежит в замысле, а
|
|
164
|
+
замысел ни там, ни там не открывают — передача пересказывает один заход, вопрос называет одну
|
|
165
|
+
развилку, и по обоим не видно ни сделанного, ни оставшегося.
|
|
166
|
+
- **Таблица показывает все задачи эпика разом — закрытые, текущую и назначенные.** Строка на
|
|
167
|
+
задачу: место по порядку, задача, состояние; текущая отличается от остальных на вид. Порядок у
|
|
168
|
+
закрытых фактический, у будущих назначенный, и расхождение между ними тоже утверждение — оно
|
|
169
|
+
говорит, что порядок пересматривали. Перечень одних оставшихся не показывает, чего работа
|
|
170
|
+
стоила; перечень одних закрытых не показывает, сколько ещё впереди.
|
|
@@ -43,6 +43,14 @@ az boards work-item update --id <номер> --title '[<номер>] …' # н
|
|
|
43
43
|
Номер в заголовок руками не пишется — он известен только после создания, и команда дописывает
|
|
44
44
|
его сама.
|
|
45
45
|
|
|
46
|
+
Заведение кончается не выводом команды, а ответом очереди работ. Команда спрашивает её сама и
|
|
47
|
+
печатает прочитанное — присутствие на доске, состояние, исполнителя; отсутствие кончает её
|
|
48
|
+
ненулевым кодом. В комментарий, в тело PR и в замысел идёт этот ответ, а не напечатанный
|
|
49
|
+
номер: номер говорит «вызов прошёл», а не «работа видна тому, кто по ней придёт».
|
|
50
|
+
|
|
51
|
+
Заведения, идущие подряд, проверяются не по последнему, а сверкой очереди целиком: промах у них
|
|
52
|
+
общий, и по одному элементу он не виден.
|
|
53
|
+
|
|
46
54
|
Чем сверить, что очередь работ в порядке:
|
|
47
55
|
|
|
48
56
|
```bash
|
|
@@ -187,7 +195,7 @@ az repos pr update --id 205 --description "$(cat тело.md)"
|
|
|
187
195
|
```
|
|
188
196
|
|
|
189
197
|
Правка описания переписывает его целиком. Тело перечитывается всякий раз, когда в ветку что-то
|
|
190
|
-
влилось после публикации:
|
|
198
|
+
влилось после публикации: PR утверждает про дерево, а дерево с тех пор изменилось.
|
|
191
199
|
|
|
192
200
|
## Состояние PR читается, а не додумывается
|
|
193
201
|
|
|
@@ -248,7 +256,7 @@ npm run task:move -- 86 in-review
|
|
|
248
256
|
15. **Набор пересмотрен после вливания главной ветки.** Он выбирается по тому, что ветка везёт
|
|
249
257
|
теперь, а не по тому, что правил автор. Ветка, не тронувшая ни строки показа, прогоняет
|
|
250
258
|
снимки витрин: с момента вливания их гоняет конвейер на её коде, и красное придёт на её
|
|
251
|
-
|
|
259
|
+
PR.
|
|
252
260
|
|
|
253
261
|
Сразу после публикации элемент переводится в разбор, и сверка очереди прогоняется ещё раз: до
|
|
254
262
|
открытия PR состояние она не судит, а после открытия расхождение видит.
|
|
@@ -46,6 +46,15 @@ gh project item-add <номер борды> --owner <владелец> --url <а
|
|
|
46
46
|
|
|
47
47
|
Последний шаг и есть тот, который забывается: без него задача заведена, но её нет в очереди.
|
|
48
48
|
|
|
49
|
+
Заведение кончается не выводом команды, а ответом очереди работ. Команда спрашивает её сама и
|
|
50
|
+
печатает прочитанное — присутствие на борде, колонку, исполнителя; отсутствие кончает её
|
|
51
|
+
ненулевым кодом. В комментарий, в тело PR и в замысел идёт этот ответ, а не напечатанный
|
|
52
|
+
номер: номер говорит «вызов прошёл», а не «задача видна тому, кто по ней работает».
|
|
53
|
+
|
|
54
|
+
Заведения, идущие подряд, проверяются не по последнему, а сверкой очереди целиком: промах у них
|
|
55
|
+
общий, и по одной задаче он не виден. Шестнадцать задач подряд напечатали номер, и ни одна не
|
|
56
|
+
попала в очередь так, чтобы её увидел владелец.
|
|
57
|
+
|
|
49
58
|
Название тикета говорит, что не так, а не что сделать: PR потом переводит его в сделанное.
|
|
50
59
|
Номер в заголовок руками не пишется — он известен только после создания, и команда дописывает
|
|
51
60
|
его сама.
|
|
@@ -227,7 +236,7 @@ $GH api -X POST "repos/$REPO/pulls/205/requested_reviewers" -f 'reviewers[]=<в
|
|
|
227
236
|
$GH api -X PATCH "repos/$REPO/pulls/205" -f body="$(cat тело.md)"
|
|
228
237
|
```
|
|
229
238
|
|
|
230
|
-
Тело перечитывается всякий раз, когда в ветку что-то влилось после публикации:
|
|
239
|
+
Тело перечитывается всякий раз, когда в ветку что-то влилось после публикации: PR
|
|
231
240
|
утверждает про дерево, а дерево с тех пор изменилось.
|
|
232
241
|
|
|
233
242
|
## Состояние PR читается, а не додумывается
|
|
@@ -270,6 +279,10 @@ npm run task:move -- 86 in-review
|
|
|
270
279
|
гоняет ничего. Линтеры, юниты и сценарии хуков снимает гейт пуша — ниже то, чего он не знает.
|
|
271
280
|
|
|
272
281
|
1. **Главная ветка влита в эту ветку** — `git fetch origin && git merge origin/main`.
|
|
282
|
+
Свежесть основания между ветками одного захода не наследуется: вторая и третья ветка
|
|
283
|
+
отводятся после своего `fetch`, а не от ссылки, подтянутой под первую. Пока идёт работа,
|
|
284
|
+
главная уходит вперёд — чаще всего собственным PR того же исполнителя, влитым час
|
|
285
|
+
назад.
|
|
273
286
|
Всё, что проверяется ниже, проверяется от этого основания: PR с разошедшейся ветки
|
|
274
287
|
показывает ревьюверу правку вперемешку с чужой. Порядок и разбор конфликта — паттерн
|
|
275
288
|
`git-workflow-merge`.
|
|
@@ -305,7 +318,7 @@ npm run task:move -- 86 in-review
|
|
|
305
318
|
15. **Набор пересмотрен после вливания главной ветки.** Он выбирается по тому, что ветка везёт
|
|
306
319
|
теперь, а не по тому, что правил автор. Ветка, не тронувшая ни строки показа, прогоняет
|
|
307
320
|
снимки витрин: с момента вливания их гоняет конвейер на её коде, и красное придёт на её
|
|
308
|
-
|
|
321
|
+
PR.
|
|
309
322
|
|
|
310
323
|
Сразу после публикации задача переставляется в разбор — `npm run task:move -- <номер>
|
|
311
324
|
in-review`, — и `npm run check:board` прогоняется ещё раз: до открытия PR колонку он не судит,
|
|
@@ -46,6 +46,14 @@ glab issue update <номер> --title '[<КЛЮЧ>-<номер>] …' # но
|
|
|
46
46
|
Метка списка ставится при заведении, а не после: issue без неё лежит вне доски, и увидеть её
|
|
47
47
|
можно только поиском по проекту.
|
|
48
48
|
|
|
49
|
+
Заведение кончается не выводом команды, а ответом очереди работ. Команда спрашивает её сама и
|
|
50
|
+
печатает прочитанное — присутствие на доске, список, исполнителя; отсутствие кончает её ненулевым
|
|
51
|
+
кодом. В комментарий, в тело PR и в замысел идёт этот ответ, а не напечатанный номер: номер
|
|
52
|
+
говорит «вызов прошёл», а не «задача видна тому, кто по ней работает».
|
|
53
|
+
|
|
54
|
+
Заведения, идущие подряд, проверяются не по последнему, а сверкой очереди целиком: промах у них
|
|
55
|
+
общий, и по одной задаче он не виден.
|
|
56
|
+
|
|
49
57
|
Чем сверить, что очередь работ в порядке:
|
|
50
58
|
|
|
51
59
|
```bash
|
|
@@ -204,7 +212,7 @@ glab mr update 205 --description "$(cat тело.md)"
|
|
|
204
212
|
|
|
205
213
|
Правка описания переписывает его целиком, поэтому строка `Closes #<номер>` пишется заново
|
|
206
214
|
вместе с остальным текстом. Тело перечитывается всякий раз, когда в ветку что-то влилось после
|
|
207
|
-
публикации:
|
|
215
|
+
публикации: PR утверждает про дерево, а дерево с тех пор изменилось.
|
|
208
216
|
|
|
209
217
|
## Состояние MR читается, а не додумывается
|
|
210
218
|
|
|
@@ -268,7 +276,7 @@ npm run task:move -- 86 in-review
|
|
|
268
276
|
15. **Набор пересмотрен после вливания главной ветки.** Он выбирается по тому, что ветка везёт
|
|
269
277
|
теперь, а не по тому, что правил автор. Ветка, не тронувшая ни строки показа, прогоняет
|
|
270
278
|
снимки витрин: с момента вливания их гоняет конвейер на её коде, и красное придёт на её
|
|
271
|
-
|
|
279
|
+
PR.
|
|
272
280
|
|
|
273
281
|
Сразу после публикации задача переставляется в разбор, и сверка очереди прогоняется ещё раз: до
|
|
274
282
|
открытия MR список она не судит, а после открытия расхождение видит.
|