@rt-tools/agent-kit 0.5.0 → 0.5.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.
Files changed (86) hide show
  1. package/README.md +73 -0
  2. package/assets/checks/check-doc-paths.mjs +200 -30
  3. package/assets/checks/check-specs.mjs +42 -7
  4. package/assets/checks/rt-kit-checks.config.mjs +12 -0
  5. package/assets/commands/agent-kit-digest.md +83 -0
  6. package/assets/commands/next-session.md +122 -0
  7. package/assets/commands/skill-curator.md +33 -1
  8. package/assets/defaults/gate-map.sh +23 -1
  9. package/assets/defaults/project.sh +37 -1
  10. package/assets/docs/GLOSSARY.md +77 -0
  11. package/assets/hooks/docs-guard.sh +18 -1
  12. package/assets/hooks/git-guard-delivery.sh +30 -3
  13. package/assets/hooks/git-guard-main.sh +8 -0
  14. package/assets/hooks/git-guard-push-tests.sh +8 -1
  15. package/assets/hooks/grill-gate.sh +38 -16
  16. package/assets/hooks/lint-after-edit.sh +10 -3
  17. package/assets/hooks/observe.sh +90 -0
  18. package/assets/hooks/postmortem-guard.sh +92 -0
  19. package/assets/hooks/profile-check.sh +43 -0
  20. package/assets/hooks/qa-dataid-guard.sh +9 -2
  21. package/assets/hooks/reuse-first-guard.sh +9 -2
  22. package/assets/hooks/skill-gate.sh +15 -0
  23. package/assets/hooks/skill-loaded.sh +7 -0
  24. package/assets/hooks/task-context-load.sh +16 -2
  25. package/assets/hooks/task-flow-guard.sh +9 -2
  26. package/assets/hooks/window-fill-guard.sh +157 -0
  27. package/assets/laws/code-structure.md +10 -0
  28. package/assets/laws/delivery.md +8 -1
  29. package/assets/laws/project-documentation.md +9 -0
  30. package/assets/laws/verifiability.md +9 -0
  31. package/assets/laws/work-conduct.md +47 -0
  32. package/assets/patterns/git-workflow-commit.azure.md +16 -12
  33. package/assets/patterns/git-workflow-commit.github.md +16 -12
  34. package/assets/patterns/git-workflow-commit.gitlab.md +16 -12
  35. package/assets/patterns/spec-driven-domain.md +19 -0
  36. package/assets/patterns/task-flow-close.md +4 -4
  37. package/assets/patterns/task-flow-handoff.md +115 -0
  38. package/assets/patterns/task-flow-resume.md +14 -2
  39. package/assets/patterns/task-flow-start.md +40 -2
  40. package/assets/rules/doc-style.md +39 -1
  41. package/assets/rules/git-workflow.azure.md +39 -0
  42. package/assets/rules/git-workflow.github.md +38 -0
  43. package/assets/rules/git-workflow.gitlab.md +38 -0
  44. package/assets/rules/spec-driven.md +14 -0
  45. package/assets/rules/task-flow.md +70 -3
  46. package/assets/skills/agent-kit.md +32 -0
  47. package/assets/templates/postmortem.md +32 -0
  48. package/assets/templates/proposal.md +39 -0
  49. package/bin/agent-kit.d.ts.map +1 -1
  50. package/bin/agent-kit.js +50 -1
  51. package/bin/agent-kit.js.map +1 -1
  52. package/lib/catalog.d.ts +33 -0
  53. package/lib/catalog.d.ts.map +1 -1
  54. package/lib/catalog.js +55 -1
  55. package/lib/catalog.js.map +1 -1
  56. package/lib/commands.d.ts +41 -0
  57. package/lib/commands.d.ts.map +1 -1
  58. package/lib/commands.js +315 -3
  59. package/lib/commands.js.map +1 -1
  60. package/lib/config.d.ts +11 -1
  61. package/lib/config.d.ts.map +1 -1
  62. package/lib/config.js +6 -0
  63. package/lib/config.js.map +1 -1
  64. package/lib/hooks-map.d.ts +15 -3
  65. package/lib/hooks-map.d.ts.map +1 -1
  66. package/lib/hooks-map.js +47 -11
  67. package/lib/hooks-map.js.map +1 -1
  68. package/lib/observations.d.ts +72 -0
  69. package/lib/observations.d.ts.map +1 -0
  70. package/lib/observations.js +126 -0
  71. package/lib/observations.js.map +1 -0
  72. package/lib/proposals.d.ts +48 -0
  73. package/lib/proposals.d.ts.map +1 -0
  74. package/lib/proposals.js +111 -0
  75. package/lib/proposals.js.map +1 -0
  76. package/lib/submit.d.ts +24 -0
  77. package/lib/submit.d.ts.map +1 -0
  78. package/lib/submit.js +26 -0
  79. package/lib/submit.js.map +1 -0
  80. package/lib/sync.d.ts +9 -1
  81. package/lib/sync.d.ts.map +1 -1
  82. package/lib/sync.js +4 -6
  83. package/lib/sync.js.map +1 -1
  84. package/package.json +1 -1
  85. package/rt-tools-agent-kit-0.5.2.tgz +0 -0
  86. package/rt-tools-agent-kit-0.5.0.tgz +0 -0
@@ -0,0 +1,157 @@
1
+ #!/usr/bin/env bash
2
+ # rt-hook: PostToolUse .*
3
+ # Требует: hooks/profile-check.sh
4
+ # rt-hook: PreToolUse .*
5
+ # Заполнение окна: заход доводится до логической точки заранее, а не обрывается на середине.
6
+ #
7
+ # Зачем именно так. Место, где исполнитель помнит ход работы, ограничено, и заполнив его, он
8
+ # теряет не последнее действие, а всю картину разом. Изнутри захода этот предел не виден ничем:
9
+ # ни одна проверка дерева его не показывает, а сжатие контекста срабатывает, когда доводить
10
+ # работу до точки уже нечем.
11
+ #
12
+ # Гард стоит на двух событиях сразу — разводить его по двум файлам значило бы держать два
13
+ # разбора одной записи и два места, где правится один порог:
14
+ # PostToolUse — на первом пороге отдаёт напоминание: пора выбирать точку остановки;
15
+ # PreToolUse — на втором отбивает всё, кроме записи хода работы, передачи и команд поставки.
16
+ # Место между порогами и есть то, на что закрывается заход: дописать ход работы, написать
17
+ # передачу, закоммитить проверенное.
18
+ #
19
+ # Размер окна берётся из настройки дерева. Из записи захода он не выводится: модель записана
20
+ # там без пометки о расширенном окне, и заход на широкое окно от захода на узкое неотличим.
21
+ #
22
+ # ОТКАЗ В ПОЛЬЗУ РАБОТЫ: нет размера окна, нет записи захода, нет разборщика, битый разбор —
23
+ # работа РАЗРЕШАЕТСЯ (exit 0). Сломанный гард не имеет права заклинить работу.
24
+
25
+ input="$(cat 2>/dev/null)"
26
+ [ -z "$input" ] && exit 0
27
+
28
+ command -v jq >/dev/null 2>&1 || exit 0
29
+
30
+ # Профиль дерева: размер окна, пороги, каталоги задач и передачи. Дерево, не задавшее размера
31
+ # окна, стража не получает — считать долю не от чего.
32
+ rt_hooks_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
33
+ 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
34
+ # shellcheck disable=SC1090
35
+ [ -f "$profile" ] && . "$profile" 2>/dev/null
36
+ done
37
+
38
+ # Слово о нехватке функции профиля: хук, вышедший молча, неотличим от работающего. Файл может
39
+ # быть не разложен — тогда остаётся прежнее поведение, молчаливое.
40
+ # shellcheck disable=SC1090
41
+ [ -f "$rt_hooks_dir/profile-check.sh" ] && . "$rt_hooks_dir/profile-check.sh"
42
+ command -v rt_needs >/dev/null 2>&1 || rt_needs() { command -v "$1" >/dev/null 2>&1; }
43
+
44
+ window="${RT_WINDOW_TOKENS:-}"
45
+ case "$window" in
46
+ '' | *[!0-9]*) exit 0 ;;
47
+ esac
48
+ [ "$window" -gt 0 ] 2>/dev/null || exit 0
49
+
50
+ warn_pct="${RT_WINDOW_WARN_PCT:-40}"
51
+ stop_pct="${RT_WINDOW_STOP_PCT:-50}"
52
+ tasks_dir="${RT_TASKS_DIR:-docs/tasks}"
53
+ handoff_dir="${RT_HANDOFF_DIR:-.claude/handoff}"
54
+
55
+ event="$(printf '%s' "$input" | jq -r '.hook_event_name // empty' 2>/dev/null)"
56
+ transcript="$(printf '%s' "$input" | jq -r '.transcript_path // empty' 2>/dev/null)"
57
+ [ -n "$transcript" ] || exit 0
58
+ [ -f "$transcript" ] || exit 0
59
+
60
+ # Заполнение — это последняя запись ответа с расходом: вход, разовая запись в кэш, прочитанное
61
+ # из кэша и вывод. Сумма по всем записям тут не годится вовсе — прочитанное из кэша повторяется
62
+ # в каждой из них, и сумма выходит в разы больше окна.
63
+ #
64
+ # Хвост в 200 строк: запись захода растёт весь заход, а нужна из неё одна последняя строка.
65
+ fill="$(tail -n 200 "$transcript" 2>/dev/null | jq -s -r '
66
+ [.[] | select(.type == "assistant") | .message.usage | select(. != null)]
67
+ | last
68
+ | if . == null then empty
69
+ else ((.input_tokens // 0) + (.cache_creation_input_tokens // 0)
70
+ + (.cache_read_input_tokens // 0) + (.output_tokens // 0))
71
+ end
72
+ ' 2>/dev/null)"
73
+
74
+ case "$fill" in
75
+ '' | *[!0-9]*) exit 0 ;;
76
+ esac
77
+
78
+ pct=$((fill * 100 / window))
79
+ fill_k=$((fill / 1000))
80
+ window_k=$((window / 1000))
81
+
82
+ # --- первый порог: напоминание, работа не отбивается -------------------------------------
83
+
84
+ if [ "$event" = "PostToolUse" ]; then
85
+ [ "$pct" -ge "$warn_pct" ] || exit 0
86
+
87
+ # Напоминание повторяется не на каждом вызове, а на каждой следующей ступени в пять
88
+ # процентов: иначе оно занимает то самое место, которое бережёт.
89
+ step=$(((pct / 5) * 5))
90
+ session="$(printf '%s' "$input" | jq -r '.session_id // "unknown"' 2>/dev/null)"
91
+ mark_dir="${TMPDIR:-/tmp}/claude-window-fill"
92
+ mark="$mark_dir/$session.step"
93
+ mkdir -p "$mark_dir" 2>/dev/null
94
+ last="$(cat "$mark" 2>/dev/null)"
95
+ case "$last" in
96
+ '' | *[!0-9]*) last=0 ;;
97
+ esac
98
+ [ "$step" -gt "$last" ] || exit 0
99
+ printf '%s' "$step" > "$mark" 2>/dev/null
100
+
101
+ if [ "$pct" -ge "$stop_pct" ]; then
102
+ text="ЗАПОЛНЕНИЕ ОКНА ${pct}% (${fill_k}k из ${window_k}k) — заход закрывается сейчас. Всё, кроме записи хода работы, передачи и команд поставки, уже отбивается."
103
+ else
104
+ text="ЗАПОЛНЕНИЕ ОКНА ${pct}% (${fill_k}k из ${window_k}k). Пора выбирать точку остановки: с ${stop_pct}% останется только закрыть заход. Доведи текущий шаг до состояния, с которого следующий заход продолжит, перепиши «Где стоим» в ходе работы, напиши передачу и отдай владельцу путь к ней — паттерн task-flow-handoff."
105
+ fi
106
+
107
+ jq -n --arg t "$text" \
108
+ '{hookSpecificOutput:{hookEventName:"PostToolUse",additionalContext:$t}}' 2>/dev/null
109
+ exit 0
110
+ fi
111
+
112
+ # --- второй порог: работа отбивается, закрытие захода пропускается ------------------------
113
+
114
+ [ "$event" = "PreToolUse" ] || exit 0
115
+ [ "$pct" -ge "$stop_pct" ] || exit 0
116
+
117
+ tool="$(printf '%s' "$input" | jq -r '.tool_name // empty' 2>/dev/null)"
118
+ path="$(printf '%s' "$input" | jq -r '.tool_input.file_path // empty' 2>/dev/null)"
119
+ cmd="$(printf '%s' "$input" | jq -r '.tool_input.command // empty' 2>/dev/null)"
120
+
121
+ allowed=0
122
+ case "$tool" in
123
+ # Разговор с владельцем и чтение того, что правится при закрытии.
124
+ AskUserQuestion | TodoWrite | Read | SendUserFile)
125
+ allowed=1
126
+ ;;
127
+ Edit | Write | MultiEdit | mcp__webstorm__create_new_file)
128
+ # Ход работы и передача. Остальное — работа, а её заход уже не начинает.
129
+ case "$path" in
130
+ "$tasks_dir"/* | */"$tasks_dir"/* | "$handoff_dir"/* | */"$handoff_dir"/* | */scratchpad/*) allowed=1 ;;
131
+ esac
132
+ ;;
133
+ Bash | mcp__webstorm__execute_terminal_command)
134
+ # Поставка и сверки: коммит, пуш, отчёт, колонка задачи, состояние дерева. Список
135
+ # дописывается профилем дерева — клиент хостинга и имена команд у каждого свои.
136
+ if rt_needs rt_handoff_allowed_cmd window-fill-guard && rt_handoff_allowed_cmd "$cmd"; then
137
+ allowed=1
138
+ fi
139
+ ;;
140
+ esac
141
+
142
+ [ "$allowed" -eq 1 ] && exit 0
143
+
144
+ reason="BLOCKED by window-fill-guard: заполнение окна ${pct}% (${fill_k}k из ${window_k}k), порог остановки ${stop_pct}%. Заход дальше не работает — он закрывается.
145
+
146
+ Что осталось сделать этим заходом:
147
+ 1. Перепиши раздел «Где стоим» в ходе работы и добавь запись захода — что сделано, чем подтверждено, что не вышло.
148
+ 2. Закоммить проверенное: незакоммиченное не переживёт перерыв.
149
+ 3. Напиши передачу в ${handoff_dir}/ и отдай владельцу путь к ней — что в неё входит, говорит паттерн task-flow-handoff.
150
+
151
+ Пропускаются при этом: правка ${tasks_dir}/**, запись передачи, команды поставки и сверки, чтение файлов и вопрос владельцу."
152
+
153
+ jq -n --arg r "$reason" \
154
+ '{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:$r}}' 2>/dev/null \
155
+ || printf '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"window-fill-guard: окно заполнено, заход закрывается передачей."}}\n'
156
+
157
+ exit 0
@@ -20,3 +20,13 @@
20
20
  причина названа рядом.
21
21
  - **Отметка об устаревании — повод убрать, а не повод оставить.** Устаревшее объявление,
22
22
  которое молча продолжает работать, переживает того, кто его пометил.
23
+
24
+ ## Открытые вопросы
25
+
26
+ - **Q-CS-3 — имя файла без обещания рода не судится ничем.** Проверка спрашивает файл, чьё имя
27
+ род называет; имя из одних слов о содержимом не говорит вовсе, и назвать род обязанным можно
28
+ только решением о продукте.
29
+ - **Q-CS-4 — одноступенчатое приведение остаётся непроверенным.** Запрещено обходить сверку
30
+ через промежуточное «неизвестно», а обычное приведение принято: часть его обязательна, и
31
+ запрет отбивал бы её вместе с остальным. Решение изменит, появится ли требование к причине у
32
+ каждого оставшегося.
@@ -16,7 +16,14 @@
16
16
  которая в одну ветку не влезает, делится на задачи до того, как ветка заводится. Признак
17
17
  деления — раздельный откат, а не объём: числа файлов, строк или коммитов, за которым работа
18
18
  становится двумя задачами, нет. Правка одного рода остаётся одной задачей, сколько бы файлов
19
- она ни задела.
19
+ она ни задела. Объём захода исполнителя признаком деления не является тоже: он говорит, какого
20
+ размера задачу стоит заводить среди тех, что делятся законно, и не даёт делить то, что
21
+ откатывается только вместе.
22
+ - **Правка самой поставки проверяется её прогоном, а не рассуждением.** Проверить её иначе
23
+ нечем: она исполняется только там, где выкатывает, и в среде, которой на месте работы нет — с
24
+ чужими правами, чужим хранилищем ключей и чужой сетью. «Проверю после слияния» решением
25
+ исполнителя не бывает: за этими словами стоит выкатка, которой уже не будет, если правка
26
+ окажется неверной. Отложить проверку может только владелец, и он говорит это словами.
20
27
  - **Две задачи, которые чинятся одной правкой, — одна задача.** Вторая стирается вместе со
21
28
  своим номером, а то, чего в первой не было, дописывается в неё до этого. Две строки об
22
29
  одной работе хуже дыры в нумерации: по ним потом не понять, что сделано, а что нет. Слить
@@ -19,6 +19,10 @@
19
19
  символ ничего не исполняет, а проверка на нём остаётся зелёной.
20
20
  - **Путь, названный в документе, существует.** Ссылка на переехавший файл читается как
21
21
  действующее указание, и следующий читатель заводит снятое заново.
22
+ - **Указатель каталога перечисляет всё, что в каталоге лежит.** Записи, которой в указателе нет,
23
+ для читателя не существует: он ищет по указателю, а не обходом каталога, и заводит разбор
24
+ заново. Это обратная сторона предыдущей статьи — не только путь из текста ведёт в файл, но и
25
+ файл назван в тексте, по которому его ищут.
22
26
  - **Документ, разошедшийся с приложением, правится тогда же, когда замечено расхождение.**
23
27
  Отложенная правка не случается: расхождение перестаёт быть заметным на следующий день.
24
28
  - **Расхождение чинится в той стороне, которая неправа, и это не всегда документ.**
@@ -43,3 +47,8 @@
43
47
  видит, проверки текстов на них не смотрят, и отказ выглядит сделанным ровно до того, как
44
48
  читатель наткнётся на снятое слово в заголовке. Читатель при этом заключает, что от слова
45
49
  не отказывались вовсе.
50
+ - **Текст, который переносится в чужое дерево, не описывает состояние этого дерева как факт.**
51
+ О соседней части он говорит условно и называет её по имени: что в дереве стоит, а чего нет,
52
+ знает само дерево, а не текст, приехавший в него. Утверждение, сказанное безусловно, врёт тем
53
+ увереннее, что печатает его сам инструмент, — и поправить его дерево не может, если правки на
54
+ месте у такого текста не предусмотрено.
@@ -47,3 +47,12 @@
47
47
  выключают в настройке инструмента, а не обходят в каждом месте.** Обход приходится повторять
48
48
  столько раз, сколько таких мест, и ни в одном из них не написано, зачем он: со стороны это
49
49
  выглядит ошибкой автора, а не решением.
50
+ - **Польза правила подтверждается наблюдением за тем, как им пользуются, а не мнением о нём.**
51
+ Правило, которого не открыли ни разу, и правило, на котором держится половина работы, в тексте
52
+ выглядят одинаково — и правится первым обычно то, о чём вспомнили, а не то, что мешает.
53
+ Наблюдение ведётся там же, где идёт работа, и переживает отдельный заход: запись, которая
54
+ умирает вместе с сессией, отвечает только на вопрос «что было минуту назад».
55
+ - **Наблюдение за работой не выносит наружу ничего, кроме того, что общее у всех.** Имя правила,
56
+ род события и версия одинаковы везде, где стоит слой правил; путь, домен и имя дерева
57
+ принадлежат одному дереву и в чужом месте не значат ничего, кроме утечки. Держится это
58
+ проверкой на выносящей стороне, а не памятью того, кто пишет.
@@ -13,8 +13,24 @@
13
13
  - **Пробел закрывается вопросом владельцу, а не догадкой.** Догадка неотличима от знания:
14
14
  она попадает в работу молча и обнаруживается только при приёмке, когда переделывать дороже
15
15
  всего.
16
+ - **Вопрос, у которого есть очевидный ответ, работу не останавливает.** Исполнитель называет
17
+ допущение, идёт дальше и записывает его туда же, где идёт работа. Останавливает только тот
18
+ пробел, при котором любая догадка делает работу опасной или бесполезной. Вопрос, заданный
19
+ вместо работы, выглядит добросовестно, а стоит владельцу захода.
20
+ - **Остановка называется первой строкой.** Сообщение, которым исполнитель останавливается,
21
+ начинается с того, чего он ждёт и что будет, если ответа не будет. Замеры, находки и разбор
22
+ к этому моменту уже записаны в ход работы — в сообщении владельцу они лишние. Чем подробнее
23
+ отчёт, тем надёжнее вопрос в нём тонет, и владелец переспрашивает, почему работа стоит.
16
24
  - **Владельцу не задаётся вопрос, ответ на который уже записан.** Записанное читают до
17
25
  разговора, а не вместо ответа: вопрос о том, что уже решено, обесценивает и остальные.
26
+ - **Вопрос владельцу задаётся после того, как ответ искали в дереве.** Что лежит в дереве,
27
+ исполнитель узнаёт сам: имя, путь, наличие файла и устройство репозитория он берёт командой,
28
+ а не у владельца. Вопрос, ответ на который дала бы одна команда, стоит владельцу захода и
29
+ обесценивает заданные рядом.
30
+ - **Утверждение о дереве стоит ровно столько, сколько команда, его показавшая.** Отрицание —
31
+ «здесь нет», «этого не заводили», «такого файла не бывает» — произносится только как вывод
32
+ команды. Не проверенное отрицание опаснее вопроса: вопрос владелец поправит, а факт от
33
+ исполнителя примет на веру, потому что тот в дерево смотрит.
18
34
  - **Решение, однажды записанное, действует, пока его не отменили, и читается до того, как
19
35
  принимается заново.** Отменённое решение следа в работе не оставляет — по результату не
20
36
  видно ни того, что его принимали, ни того, что от него отказались. Принятое заново оно
@@ -33,6 +49,14 @@
33
49
  - **Состояние незаконченной работы восстанавливается без участия владельца.** Иначе каждый
34
50
  перерыв стоит ему пересказа, а очередь работ показывает начатое и не говорит, что внутри
35
51
  него сделано.
52
+ - **Заход исполнителя конечен, и его конец не совпадает с концом работы.** Место, где
53
+ исполнитель помнит ход работы, ограничено; заполнив его, он теряет не последнее, а всё
54
+ сразу. Заход, доведённый до логической точки заранее, стоит одной записи; оборванный на
55
+ середине — целого захода на восстановление.
56
+ - **Прерванная работа передаётся следующему заходу готовым текстом, а не пересказом
57
+ владельца.** Владелец знает, что работа не кончена, но не знает, где именно она стоит;
58
+ пересказ он даёт по своей памяти, а не по ходу работы, и следующий заход начинает с чужой
59
+ картины.
36
60
  - **Замысел и ход работы — разные записи.** Замысел — то, с чем сверяют результат при
37
61
  приёмке; правленный по ходу, он перестаёт отличаться от отчёта, и приёмке сверять нечего.
38
62
  - **Сделанное отмечается в одном месте.** Две записи об одном разъезжаются молча, и после
@@ -41,6 +65,11 @@
41
65
  читается как случайное и отменяется следующим заходом, а отменённое возвращается третьим.
42
66
  - **Граница работы названа до её начала.** Не названная вслух граница не существует: правка
43
67
  расползается на соседнее, и снимать её приходится вручную.
68
+ - **Действия, которые исполнитель не делает сам, названы списком.** Всё, что уходит за
69
+ пределы рабочего дерева или не откатывается — запись в общий репозиторий, публикация, отчёт,
70
+ правка общего документа, — делается по слову владельца, и слово это даётся на действие, а не
71
+ на работу целиком. Не названная списком граница выводится из общих слов: «делай, что нужно
72
+ по плану» прочитывается как разрешение на всё, что в плане подразумевалось.
44
73
  - **Признак закрытия работы назван до её начала и проверяем.** «Работает» признаком не
45
74
  является: под ним каждый заход понимает своё, и работа закрывается тогда, когда надоела.
46
75
  - **Начатая и брошенная работа видна.** Брошенное на середине выглядит так же, как
@@ -57,3 +86,21 @@
57
86
  - **Незаданный вопрос замечает только тот, кто знает, чего хотел.** Вопрос, которого не
58
87
  задали, следа не оставляет: работа выглядит понятой ровно до приёмки, и вывести отсутствие
59
88
  вопроса не из чего.
89
+ - **Происшествие названо признаком, а не оценкой заднего числа.** Происшествие — заход, в
90
+ котором исполнитель сделал не то, а слой правил этого не отбил. Дефект в коде происшествием
91
+ не является: его объясняет договорённость о продукте. Признак записан один раз, а не
92
+ выводится каждым заходом заново — иначе его назначает тот, кому он мешает.
93
+ - **Происшествие кончается записью, и запись делается в тот же заход.** Через день механизм
94
+ промаха пересказывается уже приглаженно: остаются выводы, а из выводов правило не выводится.
95
+ Запись называет механизм промаха по шагам, что было доступно до него, чем ловилось и что из
96
+ этого ушло в слой правил.
97
+ - **Запись без правки слоя правил закрытой не считается.** Разбор, из которого не вышло ни
98
+ предложения, ни правки закона, правила или паттерна, — жалоба: он объясняет случившееся и
99
+ ничего не меняет, а значит повторится.
100
+ - **Закрытая работа оставляет то, что узнала о правилах, там, откуда это возьмёт машина.**
101
+ Понимание, добытое одной работой, всего дороже соседней — и живёт оно ровно до конца захода,
102
+ если осталось в разговоре. Записанное свободным пересказом лежит не хуже, но переносить его
103
+ приходится руками, и переносится оно ровно до первой занятой недели.
104
+ - **У предложенной правки правил назван адрес: сам слой правил, имена этого дерева или его
105
+ надстройка.** Без адреса правку кладут туда, где она видна автору, — то есть в своё дерево, —
106
+ и общее оседает в одном месте, оставаясь неизвестным всем остальным.
@@ -212,26 +212,30 @@ npm run task:move -- 86 in-review
212
212
  Конвейер видит только отправленное, а отправляется оно пушем. Линтеры, юниты и сценарии хуков
213
213
  снимает гейт пуша — ниже то, чего он не знает.
214
214
 
215
- 1. **В ветке только та правка, за которой её заводили** `git diff main...HEAD --stat`. Чужой
215
+ 1. **Главная ветка влита в эту ветку** `git fetch origin && git merge origin/main`.
216
+ Всё, что проверяется ниже, проверяется от этого основания: PR с разошедшейся ветки
217
+ показывает ревьюверу правку вперемешку с чужой. Порядок и разбор конфликта — паттерн
218
+ `git-workflow-merge`.
219
+ 2. **В ветке только та правка, за которой её заводили** — `git diff main...HEAD --stat`. Чужой
216
220
  домен в списке файлов означает, что правка расползлась, и её надо вернуть в свои границы.
217
- 2. **Ни мока, ни подменённого ответа, ни отладочной строки** — `git diff main...HEAD` читается
221
+ 3. **Ни мока, ни подменённого ответа, ни отладочной строки** — `git diff main...HEAD` читается
218
222
  целиком, а не по именам файлов. На прод они уезжают молча и портят настоящие данные.
219
- 3. **Документ едет тем же коммитом.** Пару называет `docs-guard`, но спек домена и правку его
223
+ 4. **Документ едет тем же коммитом.** Пару называет `docs-guard`, но спек домена и правку его
220
224
  поведения он не знает — это остаётся за автором.
221
- 4. **Проверки текстов и раскладки зелёные** — те, что дерево завело в `tools/`. Какие именно
225
+ 5. **Проверки текстов и раскладки зелёные** — те, что дерево завело в `tools/`. Какие именно
222
226
  есть здесь — `implementation.md` правила.
223
- 5. **Все приложения дерева собираются** — `nx build` по каждому. Гейт пуша сборку не гоняет.
224
- 6. **Видимый текст заведён во всех локалях перевода** — тестом полноты словарей, если дерево
227
+ 6. **Все приложения дерева собираются** — `nx build` по каждому. Гейт пуша сборку не гоняет.
228
+ 7. **Видимый текст заведён во всех локалях перевода** — тестом полноты словарей, если дерево
225
229
  переводится.
226
- 7. **Правка вёрстки подтверждена замером**, а не взглядом, и снята при узком экране — паттерн
230
+ 8. **Правка вёрстки подтверждена замером**, а не взглядом, и снята при узком экране — паттерн
227
231
  `browser-verification-measure`.
228
- 8. **Правка разметки публичного сайта проверена на прод-сборке по всем локалям перевода** —
232
+ 9. **Правка разметки публичного сайта проверена на прод-сборке по всем локалям перевода** —
229
233
  паттерн `seo-verify`.
230
- 9. **PR привязан к рабочему элементу**, ревьювер и исполнитель стоят.
231
- 10. **Заголовок PR несёт номер элемента и называет работу сделанной:** `[<номер>] <Что
234
+ 10. **PR привязан к рабочему элементу**, ревьювер и исполнитель стоят.
235
+ 11. **Заголовок PR несёт номер элемента и называет работу сделанной:** `[<номер>] <Что
232
236
  сделано>`, тем же номером, что стоит у элемента и в имени ветки.
233
- 11. **Очередь работ сходится** — `npm run check:board`.
234
- 12. **Состояние PR прочитано, а не выведено из кодов возврата.**
237
+ 12. **Очередь работ сходится** — `npm run check:board`.
238
+ 13. **Состояние PR прочитано, а не выведено из кодов возврата.**
235
239
 
236
240
  Сразу после публикации элемент переводится в разбор, и сверка очереди прогоняется ещё раз: до
237
241
  открытия PR состояние она не судит, а после открытия расхождение видит.
@@ -264,30 +264,34 @@ npm run task:move -- 86 in-review
264
264
  Проверок на самом PR нет: выкатка запускается пушем в главную ветку, и до мержа никто не
265
265
  гоняет ничего. Линтеры, юниты и сценарии хуков снимает гейт пуша — ниже то, чего он не знает.
266
266
 
267
- 1. **В ветке только та правка, за которой её заводили** `git diff main...HEAD --stat`. Чужой
267
+ 1. **Главная ветка влита в эту ветку** `git fetch origin && git merge origin/main`.
268
+ Всё, что проверяется ниже, проверяется от этого основания: PR с разошедшейся ветки
269
+ показывает ревьюверу правку вперемешку с чужой. Порядок и разбор конфликта — паттерн
270
+ `git-workflow-merge`.
271
+ 2. **В ветке только та правка, за которой её заводили** — `git diff main...HEAD --stat`. Чужой
268
272
  домен в списке файлов означает, что правка расползлась, и её надо вернуть в свои границы.
269
- 2. **Ни мока, ни подменённого ответа, ни отладочной строки** — `git diff main...HEAD` читается
273
+ 3. **Ни мока, ни подменённого ответа, ни отладочной строки** — `git diff main...HEAD` читается
270
274
  целиком, а не по именам файлов. На прод они уезжают молча и портят настоящие данные.
271
- 3. **Документ едет тем же коммитом.** Пару называет `docs-guard`, но спек домена и правку его
275
+ 4. **Документ едет тем же коммитом.** Пару называет `docs-guard`, но спек домена и правку его
272
276
  поведения он не знает — это остаётся за автором.
273
- 4. **Проверки текстов и раскладки зелёные** — те, что дерево завело в `tools/`: сверка
277
+ 5. **Проверки текстов и раскладки зелёные** — те, что дерево завело в `tools/`: сверка
274
278
  сценариев с тестами, путей в документах, раскладки либ, повторов и классов без правила.
275
279
  Какие именно есть здесь — `implementation.md` правила.
276
- 5. **Все приложения дерева собираются** — `nx build` по каждому. Гейт пуша сборку не гоняет:
280
+ 6. **Все приложения дерева собираются** — `nx build` по каждому. Гейт пуша сборку не гоняет:
277
281
  она длиннее всего, что он успевает сделать между командой и пушем.
278
- 6. **Видимый текст заведён во всех локалях перевода** — тестом полноты словарей, если дерево
282
+ 7. **Видимый текст заведён во всех локалях перевода** — тестом полноты словарей, если дерево
279
283
  переводится.
280
- 7. **Правка вёрстки подтверждена замером**, а не взглядом, и снята при узком экране — паттерн
284
+ 8. **Правка вёрстки подтверждена замером**, а не взглядом, и снята при узком экране — паттерн
281
285
  `browser-verification-measure`.
282
- 8. **Правка разметки публичного сайта проверена на прод-сборке по всем локалям перевода** — паттерн
286
+ 9. **Правка разметки публичного сайта проверена на прод-сборке по всем локалям перевода** — паттерн
283
287
  `seo-verify`.
284
- 9. **Тело PR начинается строкой `Closes #<номер>`**, а метки, ревьювер и исполнитель стоят.
285
- 10. **Заголовок PR несёт номер задачи и называет её сделанной:** `[<КЛЮЧ>-<номер>] <Что сделано>`,
288
+ 10. **Тело PR начинается строкой `Closes #<номер>`**, а метки, ревьювер и исполнитель стоят.
289
+ 11. **Заголовок PR несёт номер задачи и называет её сделанной:** `[<КЛЮЧ>-<номер>] <Что сделано>`,
286
290
  тем же номером, что стоит у задачи и в имени ветки. Инфинитив из задачи в него не
287
291
  переносится, тип и область коммита — тоже.
288
- 11. **Очередь работ сходится** — `npm run check:board`. Задача на борде, с исполнителем и
292
+ 12. **Очередь работ сходится** — `npm run check:board`. Задача на борде, с исполнителем и
289
293
  номером в заголовке; PR один на задачу, и закрывает он её целиком.
290
- 12. **Состояние PR прочитано, а не выведено из кодов возврата** — автор `<бот>`,
294
+ 13. **Состояние PR прочитано, а не выведено из кодов возврата** — автор `<бот>`,
291
295
  ревьювер — владелец, метки те же, что у задачи. Владельцу называют прочитанное.
292
296
 
293
297
  Сразу после публикации задача переставляется в разбор — `npm run task:move -- <номер>
@@ -232,26 +232,30 @@ npm run task:move -- 86 in-review
232
232
  Проверок на самом MR нет ровно до тех пор, пока конвейер не запущен, а запускается он пушем.
233
233
  Линтеры, юниты и сценарии хуков снимает гейт пуша — ниже то, чего он не знает.
234
234
 
235
- 1. **В ветке только та правка, за которой её заводили** `git diff main...HEAD --stat`. Чужой
235
+ 1. **Главная ветка влита в эту ветку** `git fetch origin && git merge origin/main`.
236
+ Всё, что проверяется ниже, проверяется от этого основания: MR с разошедшейся ветки
237
+ показывает ревьюверу правку вперемешку с чужой. Порядок и разбор конфликта — паттерн
238
+ `git-workflow-merge`.
239
+ 2. **В ветке только та правка, за которой её заводили** — `git diff main...HEAD --stat`. Чужой
236
240
  домен в списке файлов означает, что правка расползлась, и её надо вернуть в свои границы.
237
- 2. **Ни мока, ни подменённого ответа, ни отладочной строки** — `git diff main...HEAD` читается
241
+ 3. **Ни мока, ни подменённого ответа, ни отладочной строки** — `git diff main...HEAD` читается
238
242
  целиком, а не по именам файлов. На прод они уезжают молча и портят настоящие данные.
239
- 3. **Документ едет тем же коммитом.** Пару называет `docs-guard`, но спек домена и правку его
243
+ 4. **Документ едет тем же коммитом.** Пару называет `docs-guard`, но спек домена и правку его
240
244
  поведения он не знает — это остаётся за автором.
241
- 4. **Проверки текстов и раскладки зелёные** — те, что дерево завело в `tools/`. Какие именно
245
+ 5. **Проверки текстов и раскладки зелёные** — те, что дерево завело в `tools/`. Какие именно
242
246
  есть здесь — `implementation.md` правила.
243
- 5. **Все приложения дерева собираются** — `nx build` по каждому. Гейт пуша сборку не гоняет.
244
- 6. **Видимый текст заведён во всех локалях перевода** — тестом полноты словарей, если дерево
247
+ 6. **Все приложения дерева собираются** — `nx build` по каждому. Гейт пуша сборку не гоняет.
248
+ 7. **Видимый текст заведён во всех локалях перевода** — тестом полноты словарей, если дерево
245
249
  переводится.
246
- 7. **Правка вёрстки подтверждена замером**, а не взглядом, и снята при узком экране — паттерн
250
+ 8. **Правка вёрстки подтверждена замером**, а не взглядом, и снята при узком экране — паттерн
247
251
  `browser-verification-measure`.
248
- 8. **Правка разметки публичного сайта проверена на прод-сборке по всем локалям перевода** —
252
+ 9. **Правка разметки публичного сайта проверена на прод-сборке по всем локалям перевода** —
249
253
  паттерн `seo-verify`.
250
- 9. **Описание MR начинается строкой `Closes #<номер>`**, а метки, ревьювер и исполнитель стоят.
251
- 10. **Заголовок MR несёт номер задачи и называет её сделанной:** `[<КЛЮЧ>-<номер>] <Что
254
+ 10. **Описание MR начинается строкой `Closes #<номер>`**, а метки, ревьювер и исполнитель стоят.
255
+ 11. **Заголовок MR несёт номер задачи и называет её сделанной:** `[<КЛЮЧ>-<номер>] <Что
252
256
  сделано>`, тем же номером, что стоит у задачи и в имени ветки.
253
- 11. **Очередь работ сходится** — `npm run check:board`.
254
- 12. **Состояние MR прочитано, а не выведено из кодов возврата.**
257
+ 12. **Очередь работ сходится** — `npm run check:board`.
258
+ 13. **Состояние MR прочитано, а не выведено из кодов возврата.**
255
259
 
256
260
  Сразу после публикации задача переставляется в разбор, и сверка очереди прогоняется ещё раз: до
257
261
  открытия MR список она не судит, а после открытия расхождение видит.
@@ -89,6 +89,18 @@ docs/specs/<домен>/
89
89
  `Не покрыто: <причина>`, сценарий с неполным тестом — `Покрытие: частичное — <чего не
90
90
  хватает>`.
91
91
 
92
+ Номер в идентификаторе живёт так:
93
+
94
+ | Что случилось | Что делается с номером |
95
+ | ----------------------- | ---------------------------------------------------------------------------------------------------- |
96
+ | сценарий добавили | берётся следующий свободный — наибольший выданный в домене плюс один, а не дырка в середине |
97
+ | обещание изменили | номер тот же, заголовок теста правится тем же коммитом |
98
+ | сценарий удалили | номер остаётся пустым и новому сценарию не отдаётся; тест удаляется вместе со сценарием |
99
+ | номера захотелось сжать | не пересчитываются: связь с тестами держит только номер, а прогон остаётся зелёным при обеих правках |
100
+
101
+ Номер записывается так же, как у соседей в этом же файле: сверка ищет его шаблоном, и номер,
102
+ записанный иначе, не совпадёт ни в спеке, ни в заголовке теста.
103
+
92
104
  ## Порядок работы
93
105
 
94
106
  1. Задача заводится сценариями: что станет верно, когда работа закончится.
@@ -121,3 +133,10 @@ docs/specs/<домен>/
121
133
  - Закон, названный в тексте, но забытый в строке `**Законы:**`: по закону тогда не узнать,
122
134
  какие домены на нём стоят.
123
135
  - Правка `.proto` без спеков задетых доменов: `docs-guard` отбивает такой коммит.
136
+ - **Выросший домен делится на поддомены, а не на новые домены.** Новый домен пришлось бы
137
+ заводить в указателе, сверять с кодом отдельно и объяснять, чем он соседу не поддомен;
138
+ поддомен остаётся в своём домене и наследует его контракт. Соседний домен заводится только
139
+ тогда, когда предмет живёт своей сущностью.
140
+ - **Границу между доменами проводит владелец, а не автор очередной правки.** Автор видит свою
141
+ правку, а не то, чем предмет обрастёт: домен, заведённый по ходу дела, через месяц оказывается
142
+ половиной соседнего, и разводить их приходится вместе с номерами сценариев.
@@ -15,7 +15,7 @@ description: Паттерн правила task-flow. Брать при закр
15
15
  - Этапы замысла закрыты, проверки зелёные, отчёт готовится к публикации.
16
16
  - `npm run check:specs` перечислил договорённость в разделе «Пора вливать».
17
17
 
18
- ## 1. Договорённость вливается в спек домена
18
+ ## 9. Договорённость вливается в спек домена
19
19
 
20
20
  Последним коммитом отчёта, до слияния. Код к этому моменту написан, поэтому привязки
21
21
  `файл:символ` известны — правило въезжает в спек домена сразу проверяемым.
@@ -44,7 +44,7 @@ npm run check:specs # раздел «Пора вливать» называе
44
44
  npm run check:specs # после вливания: привязки на месте, сценарии не потерялись
45
45
  ```
46
46
 
47
- ## 2. Тексты домена приводятся к сделанному
47
+ ## 10. Тексты домена приводятся к сделанному
48
48
 
49
49
  В спек уезжает только то, что записали до кода. Остальные тексты — правила, паттерны, законы
50
50
  приложения — после правки никто не перечитывает, и они продолжают описывать старое дерево.
@@ -85,7 +85,7 @@ grep -rn -A3 "Чего из закона здесь нет" <каталог пр
85
85
  Что сделали на этом шаге, пишется в тело отчёта: что перечитали, что изменили, а если ничего
86
86
  не изменили — почему. Форма раздела — паттерн `git-workflow-commit`.
87
87
 
88
- ## 3. Папка задачи разбирается
88
+ ## 11. Папка задачи разбирается
89
89
 
90
90
  Целиком в архив не переносится: `docs/archive/` — место для записей о состоявшемся, которые
91
91
  кто-то читает, а не свалка ходов работы.
@@ -106,7 +106,7 @@ rm -r docs/tasks/<КЛЮЧ>-<номер>-<slug>
106
106
  Разбор идёт в том же отчёте, что и работа: папка, оставленная до мержа, попадает в главную
107
107
  ветку и читается там как текущая.
108
108
 
109
- ## 4. Сверка
109
+ ## 12. Сверка
110
110
 
111
111
  ```bash
112
112
  npm run check:board # папка закрытой задачи среди текущих, брошенные черновики