@rt-tools/agent-kit 0.5.0 → 0.5.1

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 (41) hide show
  1. package/README.md +5 -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/next-session.md +122 -0
  6. package/assets/defaults/gate-map.sh +21 -1
  7. package/assets/defaults/project.sh +25 -0
  8. package/assets/docs/GLOSSARY.md +74 -0
  9. package/assets/hooks/window-fill-guard.sh +150 -0
  10. package/assets/laws/code-structure.md +10 -0
  11. package/assets/laws/delivery.md +8 -1
  12. package/assets/laws/project-documentation.md +4 -0
  13. package/assets/laws/work-conduct.md +8 -0
  14. package/assets/patterns/spec-driven-domain.md +19 -0
  15. package/assets/patterns/task-flow-close.md +4 -4
  16. package/assets/patterns/task-flow-handoff.md +115 -0
  17. package/assets/patterns/task-flow-resume.md +2 -2
  18. package/assets/patterns/task-flow-start.md +4 -0
  19. package/assets/rules/doc-style.md +39 -1
  20. package/assets/rules/git-workflow.azure.md +24 -0
  21. package/assets/rules/git-workflow.github.md +23 -0
  22. package/assets/rules/git-workflow.gitlab.md +23 -0
  23. package/assets/rules/spec-driven.md +8 -0
  24. package/assets/rules/task-flow.md +46 -0
  25. package/lib/commands.d.ts.map +1 -1
  26. package/lib/commands.js +1 -0
  27. package/lib/commands.js.map +1 -1
  28. package/lib/config.d.ts +3 -1
  29. package/lib/config.d.ts.map +1 -1
  30. package/lib/config.js +2 -0
  31. package/lib/config.js.map +1 -1
  32. package/lib/hooks-map.d.ts +15 -3
  33. package/lib/hooks-map.d.ts.map +1 -1
  34. package/lib/hooks-map.js +47 -11
  35. package/lib/hooks-map.js.map +1 -1
  36. package/lib/sync.d.ts.map +1 -1
  37. package/lib/sync.js +2 -5
  38. package/lib/sync.js.map +1 -1
  39. package/package.json +1 -1
  40. package/rt-tools-agent-kit-0.5.1.tgz +0 -0
  41. package/rt-tools-agent-kit-0.5.0.tgz +0 -0
@@ -0,0 +1,74 @@
1
+ # Словарь проекта
2
+
3
+ Слова, которые в этом дереве значат что-то определённое. Читается перед тем, как написать спек,
4
+ правило, комментарий, тело коммита или описание отчёта: слово отсюда употребляется в том
5
+ значении, что здесь, а слово не отсюда либо заводится здесь же, либо заменяется простым.
6
+
7
+ Термины одного домена живут в разделе «Терминология» его спека — здесь только те, что проходят
8
+ сквозь весь проект.
9
+
10
+ Разделы ниже везёт пакет: это слова слоя правил, и значат они одно и то же везде, где он стоит.
11
+ Предметные слова дерево дописывает своими разделами через надстройку — они сливаются сюда по
12
+ заголовкам, и правка пакета их не трогает.
13
+
14
+ ## Слой правил
15
+
16
+ | Термин | Что это |
17
+ | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
18
+ | Закон | Файл в каталоге конституции. Говорит, что должно быть верно, и не знает ни путей, ни имён файлов. Верен для любого приложения этого класса |
19
+ | Законы приложения | Слой законов, верных только для этого приложения: деньги, локали, доступ. Предметность в них законна — она их предмет |
20
+ | Правило | Скил с `kind: rule`. Привязывает закон к этому дереву: чем это здесь названо и где лежит |
21
+ | Паттерн | Скил с `kind: pattern`. Готовый код и порядок действий; стоит при правиле |
22
+ | Компаньон | Файл `implementation.md` рядом с правилом: имена и пути этого дерева. Пакет знает приём, но не знает имён — их пишет проект |
23
+ | Спек | Описание домена: как он работает. Говорит об установившемся, а не о предстоящем |
24
+ | Домен | Предмет, у которого свой спек. Выросший домен делится на поддомены, а не на соседние домены |
25
+ | Сценарий | Наблюдаемое поведение под номером `SC-<ПРЕФИКС>-<НОМЕР>`. Номер стоит в заголовке теста |
26
+ | Привязка | Строка `` `файл:символ` `` в компаньоне или в спутнике спека — место, где утверждение исполняется |
27
+ | Спутник | Файл рядом со спеком или правилом: компаньон, перечень сценариев |
28
+ | Договорённость о продукте | Как продукт себя поведёт, записанное до кода. Единственное место, где спек говорит о будущем; после выкатки вливается в спек домена, а директория удаляется |
29
+ | Ресурс | Единица того, что везёт пакет правил: закон, правило, паттерн, гард, проверка, роль, команда, конвейер, шаблон, умолчание, документ |
30
+ | Раскладка | Перенос ресурса из пакета в дерево по его роду и настройке слоя |
31
+ | Разложенный файл | Файл в дереве с шапкой пакета. Правится не на месте, а надстройкой: правка на месте теряется на следующей раскладке |
32
+ | Надстройка | Файл дерева, который сливается с разложенным по заголовкам разделов |
33
+
34
+ ## Работа
35
+
36
+ | Термин | Что это |
37
+ | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
38
+ | Задача | Единица работы в очереди работ. Заводится до ветки, и номер её стоит в имени ветки и в заголовке отчёта |
39
+ | Отчёт | Заявка на слияние: то же название, что у задачи, переведённое в сделанное |
40
+ | Очередь работ | Доска, на которой видно состояние каждой задачи. Ветки она не видит |
41
+ | Папка задачи | Одна работа от разбора до слияния: разбор просьбы, замысел, ход работы. Умирает со слиянием — разбирается, и объясняющее решение уезжает в архив |
42
+ | Разбор | Расспрос владельца до первой правки. Записывается его словами и задним числом не переписывается |
43
+ | Замысел | Файл папки задачи: след задачи и этапы с признаками готовности. После написания не правится — с ним сверяют результат при приёмке |
44
+ | Ход работы | Файл папки задачи: «Где стоим», решения по ходу с причинами, записи заходов. Единственное место, где отмечается сделанное. Журналом не называется |
45
+ | След задачи | Раздел замысла: какие спеки, законы, правила и части кода работа задевает |
46
+ | Заход | Одна сессия работы над задачей. Работа живёт дольше одного захода, и между ними её состояние держит только ход работы |
47
+ | Заполнение окна | Доля места захода, которую он уже занял: вход, запись в кэш, прочитанное из кэша и вывод последнего ответа, делённые на размер окна. Не «расход» и не «бюджет»: речь о месте, а не о деньгах |
48
+ | Передача | Текст, которым заход закрывается: рабочее дерево, ветка, задача, где лежит ход работы, что сделано, следующий шаг, особенности захода. Кладётся вне дерева и не коммитится |
49
+ | Линия работ | Файл с порядком задач и зависимостями между ними, когда из одного разбора вышло несколько задач. Шире одной ветки |
50
+ | Архив | Записи о состоявшемся: что объясняет закрытое решение. После выкатки не правится |
51
+
52
+ ## Проверки
53
+
54
+ | Термин | Что это |
55
+ | --------------------- | --------------------------------------------------------------------------------------------------------------------------- |
56
+ | Гард | Хук агента, который отбивает действие до того, как оно сделано, и говорит, чем отказ снимается |
57
+ | Гейт | Требование, которое пропускает действие один раз за сессию после того, как выполнено: загружено правило, пройдены проверки |
58
+ | Отказ в пользу работы | Устройство гарда, при котором любая его поломка пропускает действие. Сломанный гард не имеет права остановить работу совсем |
59
+ | Прогон | Запуск набора сценариев. «Тесты гоняются», а не «запускаются в работу» |
60
+ | Сверка | Проверка, которая ничего не правит, а называет расхождения: раскладки с пакетом, спеков с кодом, очереди работ с ветками |
61
+ | Замер | Число, снятое с работающего приложения. Взгляд на экран замером не является |
62
+
63
+ ## Так не пишем
64
+
65
+ | Так не пишем | Пишем так |
66
+ | -------------------------- | ---------------------------------------------------------------------------------------------- |
67
+ | спека (о тесте) | тест — файл рядом с исходником; спек — документ. Одна буква разницы, а значения противоположны |
68
+ | таска, тикет | задача |
69
+ | пул-реквест, мёрдж-реквест | отчёт, а действие — слияние |
70
+ | джоба, пайплайн | конвейер и его шаг |
71
+ | хендофф | передача |
72
+ | бэклог | очередь работ |
73
+ | контекст-виндоу | окно захода, а его доля — заполнение окна |
74
+ | скилл, скилы | правило, паттерн или скил без закона — по тому, что это на самом деле |
@@ -0,0 +1,150 @@
1
+ #!/usr/bin/env bash
2
+ # rt-hook: PostToolUse .*
3
+ # rt-hook: PreToolUse .*
4
+ # Заполнение окна: заход доводится до логической точки заранее, а не обрывается на середине.
5
+ #
6
+ # Зачем именно так. Место, где исполнитель помнит ход работы, ограничено, и заполнив его, он
7
+ # теряет не последнее действие, а всю картину разом. Изнутри захода этот предел не виден ничем:
8
+ # ни одна проверка дерева его не показывает, а сжатие контекста срабатывает, когда доводить
9
+ # работу до точки уже нечем.
10
+ #
11
+ # Гард стоит на двух событиях сразу — разводить его по двум файлам значило бы держать два
12
+ # разбора одной записи и два места, где правится один порог:
13
+ # PostToolUse — на первом пороге отдаёт напоминание: пора выбирать точку остановки;
14
+ # PreToolUse — на втором отбивает всё, кроме записи хода работы, передачи и команд поставки.
15
+ # Место между порогами и есть то, на что закрывается заход: дописать ход работы, написать
16
+ # передачу, закоммитить проверенное.
17
+ #
18
+ # Размер окна берётся из настройки дерева. Из записи захода он не выводится: модель записана
19
+ # там без пометки о расширенном окне, и заход на широкое окно от захода на узкое неотличим.
20
+ #
21
+ # ОТКАЗ В ПОЛЬЗУ РАБОТЫ: нет размера окна, нет записи захода, нет разборщика, битый разбор —
22
+ # работа РАЗРЕШАЕТСЯ (exit 0). Сломанный гард не имеет права заклинить работу.
23
+
24
+ input="$(cat 2>/dev/null)"
25
+ [ -z "$input" ] && exit 0
26
+
27
+ command -v jq >/dev/null 2>&1 || exit 0
28
+
29
+ # Профиль дерева: размер окна, пороги, каталоги задач и передачи. Дерево, не задавшее размера
30
+ # окна, стража не получает — считать долю не от чего.
31
+ rt_hooks_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
32
+ 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
33
+ # shellcheck disable=SC1090
34
+ [ -f "$profile" ] && . "$profile" 2>/dev/null
35
+ done
36
+
37
+ window="${RT_WINDOW_TOKENS:-}"
38
+ case "$window" in
39
+ '' | *[!0-9]*) exit 0 ;;
40
+ esac
41
+ [ "$window" -gt 0 ] 2>/dev/null || exit 0
42
+
43
+ warn_pct="${RT_WINDOW_WARN_PCT:-40}"
44
+ stop_pct="${RT_WINDOW_STOP_PCT:-50}"
45
+ tasks_dir="${RT_TASKS_DIR:-docs/tasks}"
46
+ handoff_dir="${RT_HANDOFF_DIR:-.claude/handoff}"
47
+
48
+ event="$(printf '%s' "$input" | jq -r '.hook_event_name // empty' 2>/dev/null)"
49
+ transcript="$(printf '%s' "$input" | jq -r '.transcript_path // empty' 2>/dev/null)"
50
+ [ -n "$transcript" ] || exit 0
51
+ [ -f "$transcript" ] || exit 0
52
+
53
+ # Заполнение — это последняя запись ответа с расходом: вход, разовая запись в кэш, прочитанное
54
+ # из кэша и вывод. Сумма по всем записям тут не годится вовсе — прочитанное из кэша повторяется
55
+ # в каждой из них, и сумма выходит в разы больше окна.
56
+ #
57
+ # Хвост в 200 строк: запись захода растёт весь заход, а нужна из неё одна последняя строка.
58
+ fill="$(tail -n 200 "$transcript" 2>/dev/null | jq -s -r '
59
+ [.[] | select(.type == "assistant") | .message.usage | select(. != null)]
60
+ | last
61
+ | if . == null then empty
62
+ else ((.input_tokens // 0) + (.cache_creation_input_tokens // 0)
63
+ + (.cache_read_input_tokens // 0) + (.output_tokens // 0))
64
+ end
65
+ ' 2>/dev/null)"
66
+
67
+ case "$fill" in
68
+ '' | *[!0-9]*) exit 0 ;;
69
+ esac
70
+
71
+ pct=$((fill * 100 / window))
72
+ fill_k=$((fill / 1000))
73
+ window_k=$((window / 1000))
74
+
75
+ # --- первый порог: напоминание, работа не отбивается -------------------------------------
76
+
77
+ if [ "$event" = "PostToolUse" ]; then
78
+ [ "$pct" -ge "$warn_pct" ] || exit 0
79
+
80
+ # Напоминание повторяется не на каждом вызове, а на каждой следующей ступени в пять
81
+ # процентов: иначе оно занимает то самое место, которое бережёт.
82
+ step=$(((pct / 5) * 5))
83
+ session="$(printf '%s' "$input" | jq -r '.session_id // "unknown"' 2>/dev/null)"
84
+ mark_dir="${TMPDIR:-/tmp}/claude-window-fill"
85
+ mark="$mark_dir/$session.step"
86
+ mkdir -p "$mark_dir" 2>/dev/null
87
+ last="$(cat "$mark" 2>/dev/null)"
88
+ case "$last" in
89
+ '' | *[!0-9]*) last=0 ;;
90
+ esac
91
+ [ "$step" -gt "$last" ] || exit 0
92
+ printf '%s' "$step" > "$mark" 2>/dev/null
93
+
94
+ if [ "$pct" -ge "$stop_pct" ]; then
95
+ text="ЗАПОЛНЕНИЕ ОКНА ${pct}% (${fill_k}k из ${window_k}k) — заход закрывается сейчас. Всё, кроме записи хода работы, передачи и команд поставки, уже отбивается."
96
+ else
97
+ text="ЗАПОЛНЕНИЕ ОКНА ${pct}% (${fill_k}k из ${window_k}k). Пора выбирать точку остановки: с ${stop_pct}% останется только закрыть заход. Доведи текущий шаг до состояния, с которого следующий заход продолжит, перепиши «Где стоим» в ходе работы, напиши передачу и отдай владельцу путь к ней — паттерн task-flow-handoff."
98
+ fi
99
+
100
+ jq -n --arg t "$text" \
101
+ '{hookSpecificOutput:{hookEventName:"PostToolUse",additionalContext:$t}}' 2>/dev/null
102
+ exit 0
103
+ fi
104
+
105
+ # --- второй порог: работа отбивается, закрытие захода пропускается ------------------------
106
+
107
+ [ "$event" = "PreToolUse" ] || exit 0
108
+ [ "$pct" -ge "$stop_pct" ] || exit 0
109
+
110
+ tool="$(printf '%s' "$input" | jq -r '.tool_name // empty' 2>/dev/null)"
111
+ path="$(printf '%s' "$input" | jq -r '.tool_input.file_path // empty' 2>/dev/null)"
112
+ cmd="$(printf '%s' "$input" | jq -r '.tool_input.command // empty' 2>/dev/null)"
113
+
114
+ allowed=0
115
+ case "$tool" in
116
+ # Разговор с владельцем и чтение того, что правится при закрытии.
117
+ AskUserQuestion | TodoWrite | Read | SendUserFile)
118
+ allowed=1
119
+ ;;
120
+ Edit | Write | MultiEdit | mcp__webstorm__create_new_file)
121
+ # Ход работы и передача. Остальное — работа, а её заход уже не начинает.
122
+ case "$path" in
123
+ "$tasks_dir"/* | */"$tasks_dir"/* | "$handoff_dir"/* | */"$handoff_dir"/* | */scratchpad/*) allowed=1 ;;
124
+ esac
125
+ ;;
126
+ Bash | mcp__webstorm__execute_terminal_command)
127
+ # Поставка и сверки: коммит, пуш, отчёт, колонка задачи, состояние дерева. Список
128
+ # дописывается профилем дерева — клиент хостинга и имена команд у каждого свои.
129
+ if command -v rt_handoff_allowed_cmd >/dev/null 2>&1 && rt_handoff_allowed_cmd "$cmd"; then
130
+ allowed=1
131
+ fi
132
+ ;;
133
+ esac
134
+
135
+ [ "$allowed" -eq 1 ] && exit 0
136
+
137
+ reason="BLOCKED by window-fill-guard: заполнение окна ${pct}% (${fill_k}k из ${window_k}k), порог остановки ${stop_pct}%. Заход дальше не работает — он закрывается.
138
+
139
+ Что осталось сделать этим заходом:
140
+ 1. Перепиши раздел «Где стоим» в ходе работы и добавь запись захода — что сделано, чем подтверждено, что не вышло.
141
+ 2. Закоммить проверенное: незакоммиченное не переживёт перерыв.
142
+ 3. Напиши передачу в ${handoff_dir}/ и отдай владельцу путь к ней — что в неё входит, говорит паттерн task-flow-handoff.
143
+
144
+ Пропускаются при этом: правка ${tasks_dir}/**, запись передачи, команды поставки и сверки, чтение файлов и вопрос владельцу."
145
+
146
+ jq -n --arg r "$reason" \
147
+ '{hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:$r}}' 2>/dev/null \
148
+ || printf '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"window-fill-guard: окно заполнено, заход закрывается передачей."}}\n'
149
+
150
+ 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
  - **Расхождение чинится в той стороне, которая неправа, и это не всегда документ.**
@@ -33,6 +33,14 @@
33
33
  - **Состояние незаконченной работы восстанавливается без участия владельца.** Иначе каждый
34
34
  перерыв стоит ему пересказа, а очередь работ показывает начатое и не говорит, что внутри
35
35
  него сделано.
36
+ - **Заход исполнителя конечен, и его конец не совпадает с концом работы.** Место, где
37
+ исполнитель помнит ход работы, ограничено; заполнив его, он теряет не последнее, а всё
38
+ сразу. Заход, доведённый до логической точки заранее, стоит одной записи; оборванный на
39
+ середине — целого захода на восстановление.
40
+ - **Прерванная работа передаётся следующему заходу готовым текстом, а не пересказом
41
+ владельца.** Владелец знает, что работа не кончена, но не знает, где именно она стоит;
42
+ пересказ он даёт по своей памяти, а не по ходу работы, и следующий заход начинает с чужой
43
+ картины.
36
44
  - **Замысел и ход работы — разные записи.** Замысел — то, с чем сверяют результат при
37
45
  приёмке; правленный по ходу, он перестаёт отличаться от отчёта, и приёмке сверять нечего.
38
46
  - **Сделанное отмечается в одном месте.** Две записи об одном разъезжаются молча, и после
@@ -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 # папка закрытой задачи среди текущих, брошенные черновики
@@ -0,0 +1,115 @@
1
+ ---
2
+ name: task-flow-handoff
3
+ kind: pattern
4
+ rule: task-flow
5
+ description: Паттерн правила task-flow. Брать, когда заход упирается в заполнение окна — выбор точки остановки, запись хода работы, форма передачи и что владелец с ней делает. Не брать для возвращения к работе новым заходом — это паттерн task-flow-resume.
6
+ ---
7
+
8
+ # Закрытие захода по заполнению окна
9
+
10
+ Паттерн правила `task-flow`. Что при этом должно быть верно — закон
11
+ `docs/constitution/work-conduct.md`.
12
+
13
+ ## Когда брать
14
+
15
+ - Пришло напоминание о заполнении окна.
16
+ - Работа не влезает в заход, и это стало видно заранее.
17
+ - Заход прерывается по любой другой причине: владелец уходит, машина занята.
18
+
19
+ ## Что происходит на порогах
20
+
21
+ | Заполнение | Что делает гард | Что делает заход |
22
+ | ------------------- | ------------------------------------------------------------ | ----------------------------------------------------- |
23
+ | до первого порога | молчит | работает |
24
+ | первый порог и выше | напоминание на каждой следующей ступени в пять процентов | выбирает точку остановки и доводит до неё текущий шаг |
25
+ | второй порог и выше | отбивает всё, кроме папки задачи, передачи и команд поставки | закрывается |
26
+
27
+ Пороги сторожит гард заполнения окна; размер окна он берёт из настройки дерева — из записи
28
+ захода тот не выводится. Место между порогами и есть то, на что заход закрывается: дописать ход
29
+ работы, написать передачу, закоммитить и открыть отчёт, если работа кончена.
30
+
31
+ ## Точка остановки
32
+
33
+ Логическая точка — не «где застало напоминание», а состояние, с которого следующий заход
34
+ продолжит, ничего не переделывая:
35
+
36
+ - этап замысла закрыт целиком, а не наполовину;
37
+ - то, что сделано, проверено — прогон прошёл, сборка собрана, замер снят;
38
+ - проверенное закоммичено: незакоммиченное не переживёт перерыв;
39
+ - начатое и брошенное названо в ходе работы прямо, вместе с причиной.
40
+
41
+ Незакрытый этап — тоже законная точка, если в ходе работы записано, что именно из него сделано и
42
+ чем это подтверждено. Незаконная точка одна: правка, о которой не записано ничего.
43
+
44
+ ## 8. Заход закрывается передачей
45
+
46
+ Уборку этого шага — главную ветку, влитые ветки и запись самой передачи — делает команда
47
+ `next-session`: она проходит его целиком и называет путь к передаче последней строкой. Ниже —
48
+ что при этом должно получиться; порядок один и тот же, зовут его командой или руками.
49
+
50
+ ### Ход работы
51
+
52
+ Раздел «Где стоим» перезаписывается, решения по ходу и запись захода дописываются. Форма —
53
+ паттерн `task-flow-resume`.
54
+
55
+ ### Коммит
56
+
57
+ Проверенное коммитится сразу, а не копится до конца задачи. Работа кончена — открывается отчёт:
58
+ паттерн `git-workflow-commit`.
59
+
60
+ ### Передача
61
+
62
+ Кладётся вне дерева, одним файлом на ветку — каталог передачи называет профиль дерева:
63
+
64
+ ```bash
65
+ mkdir -p <каталог передачи>
66
+ # файл — <каталог передачи>/<ветка>.md
67
+ ```
68
+
69
+ Внутри — готовый текст для вставки в новый заход, без обращения к владельцу за подробностями:
70
+
71
+ ```markdown
72
+ Работа: <КЛЮЧ>-<номер> «<название задачи>». Рабочее дерево — <полный путь>, ветка
73
+ <КЛЮЧ>-<номер>-<slug> (заведена, в работе).
74
+
75
+ Ход работы и замысел придут на запуске сессии хуком — перечитывать их файлами не надо. Разбор
76
+ просьбы владельца лежит в папке задачи и читается, когда непонятна причина решения.
77
+
78
+ Сделано: этапы 1–3 замысла закрыты и закоммичены.
79
+ Следующий шаг: этап 4 — <что именно>.
80
+
81
+ Что учесть в этом заходе:
82
+
83
+ - стенды уже подняты владельцем, свой не поднимать;
84
+ - зависимости этого дерева отстают от главной ветки — при падении сборки на чужой ошибке
85
+ сперва установка зависимостей;
86
+ - <прочее, чего нет ни в правилах, ни в ходе работы>.
87
+ ```
88
+
89
+ Разделы фиксированы, и порядок у них тот же:
90
+
91
+ 1. **Работа** — номер задачи, её название, рабочее дерево полным путём, ветка и её состояние.
92
+ 2. **Где искать** — что придёт хуком само, а что читается по надобности.
93
+ 3. **Сделано и следующий шаг** — одной строкой каждое; подробности уже в ходе работы.
94
+ 4. **Что учесть** — особенности этого захода, которых нет ни в правилах, ни в ходе работы:
95
+ поднятые стенды, отставшие зависимости, чужие процессы на портах, незакрытые вопросы к
96
+ владельцу.
97
+
98
+ ### Путь владельцу
99
+
100
+ Последнее действие захода — назвать владельцу путь к передаче, чтобы он вставил текст в новый
101
+ заход одной вставкой. Пересказывать содержание передачи в ответе не надо: владелец её и так
102
+ прочитает, а место на неё уже потрачено.
103
+
104
+ ## Ловушки
105
+
106
+ - **Заход закрывается на втором пороге, а не начинает на нём новый этап.** Напоминание на
107
+ первом — это уже сигнал выбирать точку, а не работать дальше, пока не отобьют.
108
+ - **Передача пишется как пересказ переписки.** В неё идёт то, чего нет ни в ходе работы, ни в
109
+ правилах: дерево, ветка, состояние стендов. Всё остальное следующий заход прочитает сам.
110
+ - **Состояние работы в передачу не переезжает.** Сделанное отмечается в ходе работы — одной
111
+ записью; передача его пересказывает, но не заменяет и в дерево не коммитится.
112
+ - **Незакоммиченное не названо.** Работа живёт в дереве неделями, и строка «что лежит
113
+ несохранённым и почему» — единственное, по чему это видно.
114
+ - **Заход, кончившийся ничем, тоже пишет передачу.** «Пробовали так — не вышло, потому что» —
115
+ это и есть его результат; без записи следующий заход повторит тот же путь.
@@ -32,7 +32,7 @@ description: Паттерн правила task-flow. Брать при возв
32
32
  ней проверяется деревом — сборкой, тестами, чтением файла, — а не вопросом.
33
33
  - **Не править замысел.** С ним сверяют результат; пересмотр идёт записью в ходе работы.
34
34
 
35
- ## Первое действие захода
35
+ ## 6. Возвращение к работе новым заходом
36
36
 
37
37
  Сверить «Где стоим» с деревом. Запись описывает день, когда её сделали:
38
38
 
@@ -44,7 +44,7 @@ git log --oneline origin/main..HEAD
44
44
  Разошлось — «Где стоим» правится сразу, до работы: следующий заход поверит записи, а не
45
45
  дереву.
46
46
 
47
- ## Как ведётся ход работы
47
+ ## 7. Этап делается и отмечается в ходе работы
48
48
 
49
49
  Раздел «Где стоим» **перезаписывается**, а не дописывается — это первое, что читает следующий
50
50
  заход, и единственное, что переживает обрезку по объёму:
@@ -17,6 +17,10 @@ description: Паттерн правила task-flow. Брать в начале
17
17
 
18
18
  ## Порядок
19
19
 
20
+ Шаги ниже — начало сплошного счёта: номер шага один на весь путь работы и в следующем паттерне
21
+ не начинается заново. Весь список — в правиле `task-flow`; он же показывается владельцу в начале
22
+ работы, чтобы после шести вопросов было видно, что впереди.
23
+
20
24
  ### 1. Разведка — до первого вопроса
21
25
 
22
26
  Вопрос, ответ на который лежит в коде, владельцу не задаётся: он обесценивает и остальные.
@@ -34,8 +34,26 @@ description: Правило под «Закон о документации пр
34
34
  которые едут в репозиторий: личный черновик, закрытый `.gitignore` или
35
35
  `.git/info/exclude`, проверка не читает — мёртвая ссылка в нём держала гейт пуша, хотя ни
36
36
  в одну ветку этот файл не попадёт.
37
+ - **Голое имя и каталог судятся наравне с полным путём.** Имя без каталога ищется по всему
38
+ дереву, каталог — среди каталогов; дерево спрашивается у системы контроля версий, иначе
39
+ каталоги, начинающиеся с точки, не видны и всё, что в них лежит, читалось бы как
40
+ несуществующее. Половина строк в таблицах «Где это лежит» — как раз каталоги.
37
41
  - **Описание прошлого из проверки путей выведено целиком.** Архив по устройству называет
38
- файлы, которых уже нет, и правкой это не лечится.
42
+ файлы, которых уже нет, и правкой это не лечится. Папка задачи выведена по той же причине:
43
+ раздел находок в ходе работы перечисляет ровно то, чего в дереве нет.
44
+ - **Переносимый текст из сверки адресов выведен, как архив.** Закон, правило и паттерн написаны
45
+ для любого дерева этого класса, и адреса в них принадлежат тому дереву, куда текст ложится:
46
+ `libs/common/util` там, где корни зовутся иначе, — пример, а не мёртвая ссылка. Разложенную
47
+ копию проверка узнаёт по шапке раскладки, исходник — по каталогу, названному в настройке; без
48
+ этого сверка краснеет на полторы сотни строк, ни одна из которых не чинится здесь.
49
+ - **Указатель каталога сверяется с его содержимым обеими сторонами.** Записи каталог набирает
50
+ быстрее, чем читают его указатель, и промах не виден ни в сборке, ни в браузере: запись,
51
+ приехавшая слиянием соседней ветки, просто не попадает в таблицу. Сверенный руками указатель
52
+ расходится снова через сутки.
53
+ - **Имя, названное затем, чтобы сказать «его нет», стоит в списке исключений поимённо.**
54
+ Отличить такое упоминание от ссылки машине нечем, а текст без него теряет смысл: правило и
55
+ замысел предупреждают именно о снятом. Туда же — то, что появляется только после сборки,
56
+ имена веток и правила линтеров: выглядят адресом, адресом не являются.
39
57
  - **Документ едет в том же коммите, что и правка, которую он описывает.** Обход — строка
40
58
  `Docs-skip: <причина>` в теле коммита; пустая причина не принимается.
41
59
 
@@ -57,6 +75,19 @@ description: Правило под «Закон о документации пр
57
75
  - `doc-style-write` — как формулировать: примеры «так» и «не так», правила для комментариев.
58
76
  - `doc-style-sweep` — разбор документа, накопившего список работ, на действующее и закрытое.
59
77
 
78
+ ## Скилы дерева
79
+
80
+ Здесь дерево перечисляет свои скилы о документах — строка на скил: как он называется и какие
81
+ документы ведёт. У пакета этот раздел пуст: свои документы бывают только у дерева.
82
+
83
+ Раздел заведён затем, чтобы такому списку было куда встать. Дописанный в чужой раздел, он
84
+ уносит его с собой: надстройка сливается по заголовку `## ` и замещает пакетный раздел целиком,
85
+ поэтому приписка к «Ловушкам» стирает те пакетные пункты, которых дерево не переписывало, и
86
+ пропажу не видно ничем.
87
+
88
+ Читается этот список раньше остального: правило говорит, как формулировать, а скил дерева — что
89
+ у документа этого рода обязательно есть, вплоть до второго файла рядом.
90
+
60
91
  ## Ловушки
61
92
 
62
93
  - **Оставшаяся работа не записывается в документ, а заводится задачей.** `docs/BACKLOG.md`
@@ -105,6 +136,13 @@ description: Правило под «Закон о документации пр
105
136
  выборке руками до того, как его называют: разбор, не знающий второй формы записи, ошибается
106
137
  молча — «51 пункт без задачи» оказался шестью, потому что номер стоял и отдельной строкой, и
107
138
  в заголовке подраздела.
139
+ - **Названная в тексте проверка запускается, а не пересказывается.** «Проверка есть» и
140
+ «проверка проходит» — разные утверждения, и второго в тексте обычно нет вовсе. Из четырёх
141
+ проверок, названных правилом, три оказались не в том состоянии, в каком текст их описывает:
142
+ одна отдавала полтора десятка замечаний, вторая переписывала файлы самим запуском, третья
143
+ была красной и роняла общую сводку вместе с собой. Ни одна из трёх не входила в выкатку,
144
+ поэтому молчание было полным. Проверку, которая переписывает файлы, запускают на чистом
145
+ дереве: иначе её правки уедут чужим коммитом.
108
146
  - **Сделанность читается по дереву, а не по тексту, который о ней написан.** Это верно в обе
109
147
  стороны: строка про README обеих либ была вычеркнута как сделанная, а README остался с
110
148
  прежним числом импортёров; задача, названная владельцу несделанной, оказалась наполовину
@@ -114,3 +114,27 @@ description: Правило под «Закон о поставке» для д
114
114
  - `git-workflow-merge` — главная ветка влита в ветку задачи, конфликт разобран.
115
115
  - `git-workflow-migration` — правка схемы хранилища и её миграций.
116
116
  - `git-workflow-restart` — ручной перезапуск прода.
117
+
118
+ ## Ловушки
119
+
120
+ - **Одна работа — одна задача, сколько бы файлов она ни задела.** Числа, за которым правка
121
+ становится вторым рабочим элементом, здесь нет: делится то, что придётся откатывать порознь.
122
+ Сплошная правка текстов дерева была заведена тремя задачами «по объёму» — пришлось стирать
123
+ два рабочих элемента, закрывать два PR и переносить коммиты по одному с двумя конфликтами.
124
+ Одна из трёх не дала коммита вовсе: правка тел уже заведённых задач веткой не бывает и задачей
125
+ под ветку тоже.
126
+ - **Рабочий элемент заводится командой, а не вызовами подряд.** Доска показывает элементы своей
127
+ области и итерации, и заведённый мимо них в очереди работ не виден: со стороны это выглядит
128
+ так же, как незаведённый. Команда заведения ставит все поля разом — род, состояние,
129
+ исполнителя, область и итерацию, — и печатает готовую строку заведения ветки. Замеченный по
130
+ ходу дефект проходит тот же путь.
131
+ - **Ветка заводится вторым вызовом, а не тем же.** Гард главной ветки отклоняет составную
132
+ «создать ветку и сразу коммитить» целиком: ветки в момент разбора ещё нет.
133
+ - **Сторона конфликта бывает удалением, и «сохранить обе стороны» заводит второе объявление.**
134
+ Главная ветка снимает объявление, потому что символ переехал, — в конфликте это выглядит как
135
+ сторона, которая ничего не дописала. Разбирается чтением версии главной ветки целиком, а не по
136
+ хунку, и сверяется проверкой повторов: обе копии сами по себе исправны, сборка и линт зелёные.
137
+ - **Учётная запись для пуша и автор PR выбираются отдельно.** Если пушить пришлось из-под другой
138
+ записи, на следующий вызов это не переносится: PR открывают токеном учётной записи машинной
139
+ работы, и от того, чьей записью он открыт, зависит, кого можно назначить ревьювером. Однажды
140
+ смена записи ради пуша утекла в публикацию — отчёт вышел от владельца.