@rt-tools/agent-kit 0.8.1 → 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/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/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/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 +24 -0
- package/assets/skills/agent-kit.md +54 -6
- 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.1.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
|
@@ -21,7 +21,7 @@ description: Правило под «Закон о поставке» для д
|
|
|
21
21
|
| задача | issue проекта, заголовок `[<КЛЮЧ>-<номер>] <Что не так>`, исполнитель — учётная запись машинной работы; MR прикрепляется к нему строкой `Closes #<номер>` в описании |
|
|
22
22
|
| очередь работ | доска задач проекта — Issue Board. Задача попадает на неё меткой списка, а не самим фактом заведения: доска показывает те issue, чью метку знает |
|
|
23
23
|
| состояние задачи в очереди работ | список доски, за которым стоит метка: заведённая, взятая в работу, ждущая разбора. Имена меток — в `implementation.md`; закрытая задача уходит из очереди слиянием, а не переносом в последний список |
|
|
24
|
-
|
|
|
24
|
+
| PR о задаче | заголовок MR `[<КЛЮЧ>-<номер>] <Что сделано>` — тот же номер, что у задачи, и её название, переведённое в сделанное; тип и область коммита сюда не идут |
|
|
25
25
|
| обсуждение правки | разбор MR: ревьювер — владелец проекта, исполнитель — учётная запись машинной работы, метки — те же, что у задачи |
|
|
26
26
|
| попадание правки в главную ветку | слияние MR; оно же запускает выкатку — `.gitlab-ci.yml` |
|
|
27
27
|
| образ того коммита | `IMAGE_TAG=<sha>` в командах `docker compose` на сервере |
|
|
@@ -47,6 +47,11 @@ description: Правило под «Закон о поставке» для д
|
|
|
47
47
|
вершина главной ветки не стала предком текущей, и называет расхождение числом коммитов. MR с
|
|
48
48
|
разошедшейся ветки показывает ревьюверу свою правку вперемешку с чужой, а всё, что автор
|
|
49
49
|
проверил до публикации, он проверил от основания, которого в главной ветке уже нет.
|
|
50
|
+
- **Заведённая задача подтверждается ответом очереди работ, а не выводом команды заведения.**
|
|
51
|
+
Команда отвечает за свои вызовы: она может завести задачу и не довести её до доски, и её
|
|
52
|
+
собственный разбор ошибок этот случай называет. Напечатанный номер значит «вызов прошёл», а не
|
|
53
|
+
«задача видна тому, кто по ней работает». Спрашивается очередь — по номеру, одним вызовом, — и
|
|
54
|
+
ответ читается присутствием задачи на доске, её списком и исполнителем.
|
|
50
55
|
- **Номер ветки и номер в заголовке MR сверяются на месте, а состояние задачи — по доске.**
|
|
51
56
|
Формат читается из текста команды и работает без сети; существование задачи, её метка
|
|
52
57
|
списка, исполнитель и то, что она ещё открыта, — только когда есть чем спросить. Нет сети
|
|
@@ -56,14 +61,14 @@ description: Правило под «Закон о поставке» для д
|
|
|
56
61
|
переставляется во взятые в работу, MR открыт — в ждущие разбора; делает это команда
|
|
57
62
|
перевода, а не набор вызовов по памяти. Перевод идёт сразу за шагом, который его вызвал:
|
|
58
63
|
очередь работ читают между шагами, а не после них.
|
|
59
|
-
- **Отставший список находится сверкой очереди, а не глазами.** Сверка судит список по
|
|
64
|
+
- **Отставший список находится сверкой очереди, а не глазами.** Сверка судит список по PR
|
|
60
65
|
в обе стороны: открытый MR при задаче не в разборе и разбор без открытого MR — оба
|
|
61
66
|
расхождения. Момента, когда задачу берут в работу, ей не видно: ветки на доске нет.
|
|
62
67
|
- **Задачи, чинящиеся одной правкой, сливаются до слияния ветки.** Вторая стирается вместе с
|
|
63
68
|
номером, а недостающее из неё дописывается в первую. После слияния слить уже нельзя: ветка
|
|
64
69
|
въехала, и откатывается она целиком.
|
|
65
70
|
- **Работа, которую одним заходом не закрыть, помечена в двух местах, и они сверяются.** Метка
|
|
66
|
-
на доске и строка о заходах с передачей в
|
|
71
|
+
на доске и строка о заходах с передачей в замысле эпика говорят одно и то же двум читателям:
|
|
67
72
|
исполнитель открывает карточку раньше, чем линию, а планирует по линии. Одна пометка без
|
|
68
73
|
другой лжёт молча, поэтому сверка очереди судит пару в обе стороны. Помечается только то, что
|
|
69
74
|
законно не делится: пометка объёма правом делить не становится.
|
|
@@ -88,9 +93,9 @@ description: Правило под «Закон о поставке» для д
|
|
|
88
93
|
там кончается. Прогон команд задания на своей машине его не покрывает: он проверяет команды,
|
|
89
94
|
а не файл конвейера, — верность самого файла читается только по списку конвейеров после
|
|
90
95
|
пуша, и синтаксис отдельно судит проверка `.gitlab-ci.yml` в проекте.
|
|
91
|
-
-
|
|
96
|
+
- **PR проверяется до слияния тем же конвейером, что и главная ветка.** Проверки и сборки
|
|
92
97
|
образов идут на конвейере запроса слияния, выкатка — нет: её держит правило по главной ветке
|
|
93
|
-
у своего задания, а образ
|
|
98
|
+
у своего задания, а образ PR в реестр не уезжает.
|
|
94
99
|
- **Расхождение прода с главной веткой видно сверкой очереди работ.** Задача уходит из очереди
|
|
95
100
|
слиянием, но слияние — ещё не прод: отказавшая выкатка не трогает ни задачу, ни её список, и
|
|
96
101
|
заметить её неоткуда. Сверка спрашивает последний конвейер главной ветки и судит только
|
|
@@ -144,7 +149,7 @@ description: Правило под «Закон о поставке» для д
|
|
|
144
149
|
|
|
145
150
|
Гард поставки стоит на командах агента, поэтому ветку, заведённую руками в редакторе, он не
|
|
146
151
|
видит: имя такой ветки держится памятью. Требование от этого не слабеет — просто отдельной
|
|
147
|
-
проверки под него не заводится: работа опознаётся заголовком задачи и
|
|
152
|
+
проверки под него не заводится: работа опознаётся заголовком задачи и PR, а это сверяется
|
|
148
153
|
у всех. Сверка очереди имя ветки не судит вовсе: у открытого MR его не переименовать.
|
|
149
154
|
|
|
150
155
|
Взятие задачи в работу не стережёт ничто: доска ветки не видит, а гард поставки её видит, но
|
|
@@ -188,7 +193,7 @@ description: Правило под «Закон о поставке» для д
|
|
|
188
193
|
- **Учётная запись для пуша и автор MR выбираются отдельно.** Если пушить пришлось из-под другой
|
|
189
194
|
записи, на следующий вызов это не переносится: MR открывают токеном учётной записи машинной
|
|
190
195
|
работы, и от того, чьей записью он открыт, зависит, кого можно назначить ревьювером. Однажды
|
|
191
|
-
смена записи ради пуша утекла в публикацию —
|
|
196
|
+
смена записи ради пуша утекла в публикацию — PR вышел от владельца.
|
|
192
197
|
- **Невалидный файл конвейера виден отказом сразу после пуша, а не упавшим заданием.** Конвейер
|
|
193
198
|
на такой файл не заводится вовсе: в списке стоит запись об ошибке разбора, а внутри нет ни
|
|
194
199
|
задания, ни лога. Поэтому список конвейеров ветки смотрится тем же движением, что и пуш —
|
|
@@ -113,6 +113,10 @@ description: Правило под «Закон о документации пр
|
|
|
113
113
|
паттерны, и поиск по имени правила таких не видит: сверка ищет их полем, человек — разделом
|
|
114
114
|
«Паттерны» самого правила. Счёт паттернов, собранный приставками, выходит меньше настоящего, а
|
|
115
115
|
число потом уезжает в деление работы.
|
|
116
|
+
- **Решение из спека уходит в слой, а не в описание прошлого.** Что сверяется у спека, машина
|
|
117
|
+
знает; куда девается принятое решение — не знает и не узнает: отличить действующее требование
|
|
118
|
+
от рассказа о состоявшемся может только тот, кто спросит «останется ли это верным завтра».
|
|
119
|
+
Держится это шагом разбора закрытой работы и признаком отбора, записанным там заранее.
|
|
116
120
|
- **Якорь сверяется по сырому тексту файла, и комментарий засчитывается наравне с кодом.**
|
|
117
121
|
Существование символа проверка ищет словом по всему файлу, не вычищая комментарии, а живость
|
|
118
122
|
считает только у объявленного в коде. Имя, стоящее в одном лишь пояснении, проходит мимо обеих
|
|
@@ -22,7 +22,7 @@ description: Правило под «Закон о ведении работы»
|
|
|
22
22
|
| замысел | `docs/tasks/<ветка>/plan.md` — след задачи и этапы с признаками готовности; после написания не правится |
|
|
23
23
|
| ход работы | `docs/tasks/<ветка>/progress.md` — «Где стоим», решения по ходу, записи заходов; единственное место, где отмечается сделанное |
|
|
24
24
|
| договорённость о продукте, записанная до кода | `docs/specs/<домен>/proposed/<фича>/` — спек фичи; переживает мерж и вливается в спек домена |
|
|
25
|
-
| работа шире одной ветки
|
|
25
|
+
| эпик — работа шире одной ветки | карточка в очереди работ с меткой эпика и файл замысла рядом: возможность, состав задач и их порядок |
|
|
26
26
|
| папка задачи до заведения задачи | `docs/tasks/_draft-<slug>/` — вне истории, пока номера нет |
|
|
27
27
|
| разведка | заход `Explore` или `general-purpose` до первого вопроса владельцу |
|
|
28
28
|
| разбор замысла ролями | `.claude/workflows/plan.js` — нужность, договорённость, критика, замысел |
|
|
@@ -53,6 +53,7 @@ description: Правило под «Закон о ведении работы»
|
|
|
53
53
|
| 10 | Тексты домена приводятся к сделанному | `task-flow-close` |
|
|
54
54
|
| 11 | Папка задачи разбирается | `task-flow-close` |
|
|
55
55
|
| 12 | Сверка очереди работ | `task-flow-close` |
|
|
56
|
+
| 13 | Следующая задача эпика берётся тем же движением | `task-flow-resume` |
|
|
56
57
|
|
|
57
58
|
Шаги 6–8 повторяются, пока этапы замысла не кончатся: первый заход входит в работу шагом 1 и
|
|
58
59
|
доходит до 7, дальше каждый следующий начинается шагом 6. Шаги 9–12 идут один раз, когда работа
|
|
@@ -67,17 +68,36 @@ description: Правило под «Закон о ведении работы»
|
|
|
67
68
|
по имени ветки, `plan.md` в ней и названную в его шапке договорённость о продукте.
|
|
68
69
|
- **Влитая договорённость ветку не запирает.** После вливания директории «предложено» на диске
|
|
69
70
|
нет, а замысел на неё ссылается до конца работы: гард отличает влитое от незаведённого по
|
|
70
|
-
истории ветки и пропускает первое. Иначе последний коммит
|
|
71
|
+
истории ветки и пропускает первое. Иначе последний коммит PR закрывал бы дорогу правкам
|
|
71
72
|
по замечаниям разбора.
|
|
72
73
|
- **Договорённость требуется по путям правки, а не по оценке задачи.** `apps/**` и `libs/**`
|
|
73
74
|
— признак; правила, тексты, обвязка и зависимости под него не подпадают. Обход — строка
|
|
74
75
|
`**Поведение:** не меняется — <причина владельца>` в замысле; пустая причина не
|
|
75
76
|
принимается.
|
|
76
|
-
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
- **Папка задачи заводится под любую работу, без исключений.** Прежде правило судило по числу
|
|
78
|
+
заходов: работа в один коммит помещалась в тело PR и папки не заводила. Исключение,
|
|
79
|
+
у которого есть хоть одна законная форма, исполняется как разрешение — за один заход оно
|
|
80
|
+
дважды стало поводом обойти отказ гарда, вместо того чтобы завести папку и пойти дальше.
|
|
81
|
+
Заводится она всегда и до первой правки; сколько заходов уйдёт на работу, заранее не знает
|
|
82
|
+
никто.
|
|
83
|
+
- **Открыв PR, исполнитель называет владельцу три вещи: номер, чего ждёт и что сделает
|
|
84
|
+
следом.** Ждёт он прогона — до его конца о работе ничего не известно, кроме того, что она
|
|
85
|
+
запушена. Следом идёт уборка: разбор папки задачи последним коммитом. Сказанное так владелец
|
|
86
|
+
читает однозначно, а зелёный прогон на странице — нет: он говорит, что не сломано, и молчит
|
|
87
|
+
о том, что ветка ждёт ещё одного коммита. Трижды подряд PR был влит внутри этого молчания.
|
|
88
|
+
- **Просьба о слиянии — отдельный ход, и раньше уборки её не бывает.** Порядок один: PR открыт
|
|
89
|
+
→ прогон зелёный → папка задачи разобрана и запушена → исполнитель просит влить, называя
|
|
90
|
+
номер. До этой просьбы работа не готова, сколько бы зелёного на её странице ни было.
|
|
91
|
+
- **Пока PR ждёт разбора, исполнитель берёт следующую задачу.** Ожидание чужого шага заходом
|
|
92
|
+
не занимают: работа уходит на разбор, и тем же движением берётся следующая. Готовым к
|
|
93
|
+
слиянию прежний PR становится не сам — его доводит до готовности исполнитель, вернувшись к
|
|
94
|
+
нему тем же ходом, которым прочитал конец прогона.
|
|
95
|
+
- **Отказ гарда кончает ход.** Другого пути к отбитой правке не ищут: ни командой оболочки, ни
|
|
96
|
+
соседним инструментом, ни правкой самого гарда. Отбитая правка либо делается после того, как
|
|
97
|
+
условие отказа выполнено, либо не делается вовсе — и тогда владельцу называется отказ, а не
|
|
98
|
+
результат. Обход стоит дороже отказа: гард отбивает один файл, а обойдённый гард снимает
|
|
99
|
+
требование со всего дерева и молчит об этом. Держится это не только памятью — гарды судят и
|
|
100
|
+
команду оболочки, которая пишет файл.
|
|
81
101
|
- **Ход, в котором владельцу задан вопрос, не заканчивается, пока за этот же ход не читались
|
|
82
102
|
законы и правила.** Чтением считается любой из трёх путей: загрузка правила, чтение файла
|
|
83
103
|
законов или правил, поиск по ним. Отбивает гард разговора — на завершении хода, а не на
|
|
@@ -113,24 +133,24 @@ description: Правило под «Закон о ведении работы»
|
|
|
113
133
|
`npm run task:new` переименовывает черновик и проставляет шапку замысла.
|
|
114
134
|
- **Брошенный разбор виден.** Черновик старше недели перечисляет сверка очереди работ —
|
|
115
135
|
задачи за ним ещё нет, и спросить о нём некого.
|
|
116
|
-
- **Договорённость вливается в спек домена последним коммитом
|
|
136
|
+
- **Договорённость вливается в спек домена последним коммитом PR.** К этому моменту код
|
|
117
137
|
написан, привязки известны, и в главной ветке директория `proposed/` не появляется вовсе.
|
|
118
138
|
Готовые к вливанию перечисляет `npm run check:specs`.
|
|
119
139
|
- **Папка закрытой задачи разбирается, а не переносится целиком.** В `docs/archive/` уезжает
|
|
120
140
|
то, что объясняет состоявшееся решение; остальное удаляется. Неразобранную ловит сверка
|
|
121
141
|
очереди работ.
|
|
122
142
|
- **Слияние отбивается, пока ветка везёт папку своей задачи.** Требование стоит на слиянии, а
|
|
123
|
-
не на открытии
|
|
124
|
-
же ветку, а без замысла на диске её отбивает гард хода работы. На открытии
|
|
143
|
+
не на открытии PR: до слияния папка ещё нужна — правка по замечаниям разбора идёт в ту
|
|
144
|
+
же ветку, а без замысла на диске её отбивает гард хода работы. На открытии PR о лежащей
|
|
125
145
|
папке говорится вслух, и только. Судится содержимое ветки, а не рабочее дерево: снесённая,
|
|
126
146
|
но не закоммиченная папка въехала бы вместе с веткой.
|
|
127
147
|
- **Ветка, снёсшая папку, обязана прибавить запись в архив.** Снести дешевле, чем разобрать, и
|
|
128
148
|
первым уходит разбор просьбы — единственная запись слов владельца. Что именно увезено,
|
|
129
149
|
требование не судит: это судит владелец.
|
|
130
|
-
- **Обход — строка `Task-folder-skip: <причина>` в
|
|
150
|
+
- **Обход — строка `Task-folder-skip: <причина>` в PR или в самой команде слияния.**
|
|
131
151
|
Работа, вливаемая частями, папку до конца не разбирает. Чтение из команды работает и без
|
|
132
152
|
сети: единственный сетевой путь отбивал бы оффлайн то самое слияние, причина которого
|
|
133
|
-
написана в
|
|
153
|
+
написана в PR. Пустая причина обходом не считается, а сам обход снимает отказ, но не
|
|
134
154
|
гасит строку сверки очереди — иначе он через месяц становится рабочим путём.
|
|
135
155
|
|
|
136
156
|
## Чего из закона здесь нет
|
|
@@ -171,7 +191,7 @@ description: Правило под «Закон о ведении работы»
|
|
|
171
191
|
Что именно перенесли в архив, не проверяется. Гард видит, что папка уезжает в главную ветку и
|
|
172
192
|
что ветка что-то в архив добавила, но не может судить, то ли это и стоило ли переносить именно
|
|
173
193
|
это. Сверять содержимое машине нечем — смотрит владелец на ревью. Отсюда же и обход: если
|
|
174
|
-
работа вливается частями, папку до конца не разбирают, а причина остаётся в
|
|
194
|
+
работа вливается частями, папку до конца не разбирают, а причина остаётся в PR.
|
|
175
195
|
|
|
176
196
|
## Паттерны
|
|
177
197
|
|
|
@@ -207,16 +227,21 @@ description: Правило под «Закон о ведении работы»
|
|
|
207
227
|
задаче так ушли две правки подряд: сначала подняли общее число у соседнего узла, потом
|
|
208
228
|
перенесли узел в другое место разметки. Обе владелец отверг, а нужный способ назвал сам.
|
|
209
229
|
Спрашивают до правки, а не показывают замер после.
|
|
210
|
-
-
|
|
230
|
+
- **Эпик по теме читается до того, как решается раскладка.** Замысел эпика держит решения,
|
|
211
231
|
которые пережили десяток задач, и разведка по коду их не находит: снятое решение следа в
|
|
212
|
-
дереве не оставляет. Домен, заведённый генератором и снесённый через полчаса, стоял в
|
|
213
|
-
прямым запретом — но
|
|
214
|
-
- **Работа, которая разбирает папку задачи,
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
232
|
+
дереве не оставляет. Домен, заведённый генератором и снесённый через полчаса, стоял в замысле
|
|
233
|
+
прямым запретом — но замысел открыли уже после того, как он был заведён во второй раз.
|
|
234
|
+
- **Работа, которая разбирает чужую папку задачи, разбирает и свою — одним коммитом.** Свою
|
|
235
|
+
папку она заводит наравне со всеми: исключения из этого требования нет. Круг, которым
|
|
236
|
+
исключение оправдывали, закрывается не отказом от папки, а порядком разбора: последний
|
|
237
|
+
коммит снимает обе, и после работы неубранного не остаётся. Однажды такой разбор оставил
|
|
238
|
+
свою папку, и на неё пришлось заводить третью задачу — лечится это порядком, а не правом
|
|
239
|
+
работать без замысла на диске. Как разобрать две папки — паттерн `task-flow-close`.
|
|
220
240
|
- **Слово для нового понятия берётся из `docs/GLOSSARY.md` или заводится там же.** Третий файл
|
|
221
241
|
папки задачи называется `progress.md`, а не `journal.md`, ровно поэтому: журнал в этом
|
|
222
242
|
дереве один, и он другой.
|
|
243
|
+
- **Черновик папки задачи называется тем же коротким именем, что и будущая ветка.** Команда
|
|
244
|
+
заведения ищет черновик по нему и, не найдя, молча собирает папку с образца: работа при этом
|
|
245
|
+
идёт дальше, а разбор просьбы остаётся лежать в брошенном каталоге, и следующий заход
|
|
246
|
+
расспрашивает владельца заново. Имя черновику дают словами просьбы, а ветке — терминологией
|
|
247
|
+
договорённости; те же слова, да не те же.
|
package/assets/rules/testing.md
CHANGED
|
@@ -60,6 +60,10 @@ description: Правило под «Закон о проверяемости».
|
|
|
60
60
|
Сводная цель запускается руками, и проверка, которая живёт только в ней, отвечает тому, кто
|
|
61
61
|
её вспомнил: молчание такой проверки читается как её зелёный ответ. Три проверки простояли
|
|
62
62
|
вне гейта, объявляя в собственных списках известного, что падают на новом.
|
|
63
|
+
- **Проверка, приехавшая раскладкой, приезжает и со своим местом.** Место — это имя команды,
|
|
64
|
+
которой её зовут, и строка набора, в котором она стоит. Проверка без места узнаётся только по
|
|
65
|
+
тому, что раскладка положила новый файл, и статья выше на неё не действует: вставать ей некуда.
|
|
66
|
+
Так приехала проверка длины — той же редакцией, что и статья о её обязательном месте.
|
|
63
67
|
- **Спека, необратимо меняющая данные стенда, выключена по умолчанию.** `BASE_URL` уводит
|
|
64
68
|
прогон одной переменной, и без выключателя такая спека правила бы данные чужого стенда.
|
|
65
69
|
- **Спеки, которым нужен nginx перед приложением, просыпаются вместе с `BASE_URL`.** Голый
|
|
@@ -78,6 +82,10 @@ description: Правило под «Закон о проверяемости».
|
|
|
78
82
|
принятое остаётся навсегда, долг накоплен к заведению проверки и только сокращается, — либо
|
|
79
83
|
столько ключей, сколько у записей родов. Причина обязательна: снятая проверка без причины
|
|
80
84
|
через месяц неотличима от недосмотра.
|
|
85
|
+
- **Строка в список известного не заводится под красную проверку.** Список набран к дню
|
|
86
|
+
заведения проверки и с тех пор только сокращается: дописанная строка гасит сигнал, а не
|
|
87
|
+
причину, и в истории выглядит так же, как починка. Место, где проверка права по букве и не
|
|
88
|
+
права по существу, разбирает владелец, а до его ответа верна проверка.
|
|
81
89
|
- **Тест, утверждающий отсутствие, зелен и тогда, когда ищет не то.** Совпадения нет ни у
|
|
82
90
|
верного текста, ни у опечатки в образце, ни у переименованного ключа — отличить их по цвету
|
|
83
91
|
прогона нечем. Отрицательное утверждение поэтому идёт в паре с положительным: сначала
|
|
@@ -136,3 +144,14 @@ description: Правило под «Закон о проверяемости».
|
|
|
136
144
|
стенда. Обещанное поведение остаётся сценарием в `scenarios.md`: если списать его во второе
|
|
137
145
|
место, копии разойдутся молча — `npm run check:specs` этого не увидит.
|
|
138
146
|
- `npx nx serve` проверкой не является: это шаг из правила `browser-verification`, а не тест.
|
|
147
|
+
- **Кадр, зависящий от загрузки машины, проверяет машину, а не вёрстку.** Ожидание отсчётом
|
|
148
|
+
времени этим и кончается: на свободной машине набор зелен целиком, на занятой падает, и какой
|
|
149
|
+
именно кадр не успел — дело случая. Лечится ожиданием события, а не удлинением отсчёта: шрифты
|
|
150
|
+
подняты, картинки нарисованы, движение остановлено, положение узла не менялось два кадра
|
|
151
|
+
подряд. Пока ожидание идёт по времени, «проверено снимками» означает «машина была свободна», и
|
|
152
|
+
перезапуск, давший зелёное, этого не отменяет, а прячет. Восемь кадров расходились с эталоном
|
|
153
|
+
на 0,15–0,74 % в задании конвейера и проходили на той же машине вне его.
|
|
154
|
+
- **Стенд, поднятый предыдущим шагом, останавливается перед съёмкой.** Оставленный работать, он
|
|
155
|
+
соревнуется за машину с тем, что снимают, и делает исход прогона зависящим от того, чем занят
|
|
156
|
+
сосед. Нагрузка, которую задание создаёт себе само — соседняя витрина, только что законченная
|
|
157
|
+
сборка, — ничем не отличается от чужой.
|
|
@@ -69,6 +69,18 @@ description: Правило под «Закон об устройстве код
|
|
|
69
69
|
|
|
70
70
|
## Ловушки
|
|
71
71
|
|
|
72
|
+
- **Пределы сложности функции спрашивают у плагина, а не вспоминают.** Там, где дерево подняло
|
|
73
|
+
правила `sonarjs` разом, до отказа, числа ветвлений и вложенности приходят умолчаниями
|
|
74
|
+
плагина и своей строкой в конфиге не записаны: они меняются вместе с его версией, а выглядят
|
|
75
|
+
как договорённость дерева. За одну задачу их спрашивали трижды, каждый раз заново, и дважды
|
|
76
|
+
называли по памяти — оба раза мимо.
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
node -e 'const s = require("eslint-plugin-sonarjs");
|
|
80
|
+
for (const n of ["cyclomatic-complexity", "cognitive-complexity", "nested-control-flow"])
|
|
81
|
+
console.log(n, JSON.stringify(s.rules[n].meta.defaultOptions));'
|
|
82
|
+
```
|
|
83
|
+
|
|
72
84
|
- Приведение через `as Type` в маппере запрещено, но не стережётся ничем: оно принимает любое
|
|
73
85
|
значение и компилируется. Вместо него — `this.typeCast`.
|
|
74
86
|
- Неиспользуемый параметр убирается, а не переименовывается: подчёркивание перед именем прячет
|
|
@@ -42,6 +42,20 @@ description: Готовые примеры того, как дерево доп
|
|
|
42
42
|
выглядит собранным. Поэтому заголовок в примере выше свой. Пакетный заголовок берут только
|
|
43
43
|
тогда, когда пакетный текст здесь неверен и его правда надо снять.
|
|
44
44
|
|
|
45
|
+
**Заголовок, стоящий внутри примера, разделом не является.** Разбор пропускает всё, что лежит
|
|
46
|
+
в ограде блока кода: образец документа с собственными заголовками рвал бы ресурс на куски.
|
|
47
|
+
Поэтому надстройка, названная таким заголовком, не замещает ничего — она попадает в строку «нет
|
|
48
|
+
у пакета» и дописывается новым разделом в конец. Правка при этом выглядит сработавшей: файл
|
|
49
|
+
собран, `sync --check` зелёный, а нужный абзац остался прежним.
|
|
50
|
+
|
|
51
|
+
Дотягиваются до него заголовком того раздела, внутри которого он лежит, — и замещают этот
|
|
52
|
+
раздел целиком, вместе с примером:
|
|
53
|
+
|
|
54
|
+
````bash
|
|
55
|
+
# какие заголовки у ресурса на самом деле — примеры в ограде сюда не попадают
|
|
56
|
+
awk '/^```/ { fence = !fence } !fence && /^## / { print }' <файл ресурса>
|
|
57
|
+
````
|
|
58
|
+
|
|
45
59
|
Проверяется раскладкой: `sync`, затем `sync --check` — и глазами по разложенному файлу, на
|
|
46
60
|
месте ли пакетные разделы.
|
|
47
61
|
|
|
@@ -140,6 +154,10 @@ rt_docs_pair_for() {
|
|
|
140
154
|
- **Правка на месте вместо надстройки.** Разложенный файл узнаётся по шапке, а не по каталогу:
|
|
141
155
|
раскладка ложится в те же `tools/` и `.claude/`, где лежит своё.
|
|
142
156
|
- **Свой пункт дописан к пакетному заголовку** — пакетные пункты этого раздела ушли молча.
|
|
157
|
+
- **Надстройка названа заголовком, который стоит в примере.** Заместить она ничего не может —
|
|
158
|
+
такого раздела у ресурса нет, — и уезжает новым разделом в конец. Видно это глазами по
|
|
159
|
+
разложенному файлу: два одинаковых заголовка, один в ограде примера, другой последним
|
|
160
|
+
разделом; раскладка при этом зелёная, потому что расхождения с пакетом нет.
|
|
143
161
|
- **Функция объявлена заново без вызова `_default`** — вместе со своим случаем потеряны все
|
|
144
162
|
пакетные.
|
|
145
163
|
- **Общая ветка карты стоит выше частной** — частная не выполняется никогда.
|
|
@@ -147,3 +165,9 @@ rt_docs_pair_for() {
|
|
|
147
165
|
отвечает ненулевым кодом, то есть «правка отбита». После правки — `bash -n`.
|
|
148
166
|
- **Правка ресурса пакета без сборки.** Строка запуска читает собранное, а не исходники:
|
|
149
167
|
порядок всегда один — правка, сборка, `sync`.
|
|
168
|
+
- **Форматтер правит ресурс на коммите, и раскладка отстаёт задним числом.** Разложенное
|
|
169
|
+
сходилось в ту минуту, когда его раскладывали, а ресурс изменился после: пример с оградой
|
|
170
|
+
внутри примера форматтер переписывает на ограду длиннее, сумма ресурса меняется, и
|
|
171
|
+
`sync --check` краснеет уже на следующем шаге. Порядок обхода: прогнать форматтер на
|
|
172
|
+
правленом ресурсе, потом `sync`, потом коммит — либо переразложить и добавить в тот же
|
|
173
|
+
коммит.
|
|
@@ -27,6 +27,7 @@ description: Переносимый слой правил агента — за
|
|
|
27
27
|
| какие признаки единообразия дерево берёт | `checks.json`, ключи `reuse.bundles` и `reuse.signals` |
|
|
28
28
|
| раздел разложенного текста | `.claude/rt-kit/overrides/<идентификатор ресурса>` |
|
|
29
29
|
| что брать, а от чего отказаться | `.claude/rt-kit.json`, ключи `only` и `skip` |
|
|
30
|
+
| что у дерева есть: хранилище, админка, пакеты | `.claude/rt-kit.json`, ключ `has` |
|
|
30
31
|
| сам механизм — гард, проверка, текст правила | ресурс в пакете |
|
|
31
32
|
|
|
32
33
|
Надстройка объявляет функцию заново и вправе позвать умолчание тем же именем с суффиксом
|
|
@@ -49,7 +50,7 @@ npx agent-kit doctor # что разложено, что отстало,
|
|
|
49
50
|
npx agent-kit sync # разложить
|
|
50
51
|
npx agent-kit sync --check # ничего не писать, отказать при расхождении
|
|
51
52
|
npx agent-kit stats # чем пользовались, чем ни разу, обо что спотыкались
|
|
52
|
-
npx agent-kit propose # отправить
|
|
53
|
+
npx agent-kit propose # отправить груз в приём: сводку, предложения и разборы
|
|
53
54
|
```
|
|
54
55
|
|
|
55
56
|
## Обратная связь наверх
|
|
@@ -65,11 +66,29 @@ npx agent-kit propose # отправить предложения, адр
|
|
|
65
66
|
|
|
66
67
|
**Предложения** приносит разбор закрытой задачи — командой `/skill-curator`. Каждому он ставит
|
|
67
68
|
адрес: «пакет», «компаньон» или «дерево». Выгружаются они файлом в `.claude/rt-kit/proposals/`
|
|
68
|
-
(форма — шаблон `proposal.md`), а `agent-kit propose`
|
|
69
|
-
пакету, вместе со
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
(форма — шаблон `proposal.md`), а `agent-kit propose` увозит в приём те, что адресованы
|
|
70
|
+
пакету, вместе со сводкой и разборами происшествий. Адрес дерева в сводке или в тексте
|
|
71
|
+
предложения отбивает отправку целиком.
|
|
72
|
+
|
|
73
|
+
Приём — закрытая служба: сводка говорит о рабочих привычках команды, и в открытой очереди работ
|
|
74
|
+
это выложено всему свету. Адрес приёма объявляется ключом `intake` в конфиге дерева, токен —
|
|
75
|
+
ключом `token`, и лежит он вне дерева.
|
|
76
|
+
|
|
77
|
+
**Отметка об отправке в файле предложения — след для человека, а не хранилище состояния.** Файл
|
|
78
|
+
живёт в рабочем дереве, а дерево у каждой ветки своё: отметка, поставленная в одной ветке, в
|
|
79
|
+
соседней не видна, и тот же текст уезжает вторым разом. Второй записью он при этом не
|
|
80
|
+
становится — приём отбирает уже приехавшее по признаку предложения, и его ответ говорит,
|
|
81
|
+
сколько записей легло и сколько уже лежало. Строка «принято 0, уже лежало 3» означает, что
|
|
82
|
+
нового не уехало ничего.
|
|
83
|
+
|
|
84
|
+
Разбираются предложения в репозитории самого пакета — командой `/agent-kit-digest`, там же, где
|
|
85
|
+
лежат правимые ресурсы и видно всех потребителей сразу.
|
|
86
|
+
|
|
87
|
+
**Имя файла предложения в текстах дерева не называется.** Каталог предложений в историю не едет:
|
|
88
|
+
файл лежит на той машине, где его написали, и адрес на него ведёт в пустоту у всех остальных —
|
|
89
|
+
проверка путей краснеет в каждом дереве, кроме одного, а читателю ссылка не даёт ничего.
|
|
90
|
+
Написанное в разборе происшествия и в любом другом тексте репозитория говорит, кому предложение
|
|
91
|
+
отправлено и о чём оно; ресурс пакета при этом называть можно — он в истории есть.
|
|
73
92
|
|
|
74
93
|
Предложение работу не выправляет. Оно лежит текстом, читается глазами и в контекст сам собой
|
|
75
94
|
не приходит: замечание было прочитано, процитировано владельцу и нарушено в том же ходе —
|
|
@@ -77,6 +96,14 @@ npx agent-kit propose # отправить предложения, адр
|
|
|
77
96
|
только войдя в ресурс пакета; до этого на него не ссылаются как на действующее требование и не
|
|
78
97
|
считают дырку закрытой.
|
|
79
98
|
|
|
99
|
+
**Слово владельца о предложении — «отправь», «заведи», «напиши пропозал» и любая другая форма
|
|
100
|
+
того же — исполняется отправкой в тот же ход.** Сухой прогон отправкой не является: он
|
|
101
|
+
показывает, что уехало бы, ничего не заводит и следа наружу не оставляет. Неудобна отправка
|
|
102
|
+
ровно в одном месте — она пишет отметки в файлы предложений и делает дерево грязным; при
|
|
103
|
+
открытом PR отметки ложатся вторым коммитом в ту же ветку, и это их место, а не повод
|
|
104
|
+
отложить. Стережёт это гард предложения на завершении хода — там же, где стоит гард
|
|
105
|
+
происшествия, и по той же причине.
|
|
106
|
+
|
|
80
107
|
## Установка туда, где уже всё своё
|
|
81
108
|
|
|
82
109
|
1. `init`, затем `skip` на всё, что дерево держит само. Пустая раскладка — законное начало.
|
|
@@ -86,6 +113,27 @@ npx agent-kit propose # отправить предложения, адр
|
|
|
86
113
|
4. Разложенное поверх своего пакет не пишет: файл без шапки для него чужой. Снять его —
|
|
87
114
|
решение владельца, и до этого раскладка отказывает поимённо.
|
|
88
115
|
|
|
116
|
+
## Свойства дерева
|
|
117
|
+
|
|
118
|
+
Часть правил пакета верна только там, где есть хранилище, админка или приложение. Дерево
|
|
119
|
+
перечисляет, что у него есть, ключом `has`; ресурс называет нужное ему свойство приставкой в
|
|
120
|
+
имени — `observability.needs-app.md`, — и дереву, которое такого свойства не назвало, не
|
|
121
|
+
кладётся вовсе: ни он сам, ни черновик его компаньона.
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{ "has": ["packages", "app"] }
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
- **Молчание требованию не отвечает.** Дерево с пустым `has` не получает ни одного помеченного
|
|
128
|
+
ресурса: положенный наугад, он вернётся пустым компаньоном, заполнить который нечем.
|
|
129
|
+
- **Требование — не вид.** Вид отвечает на «какой из трёх» и выбирается один; свойств у дерева
|
|
130
|
+
сразу несколько, и дерево, которое публикует пакеты и держит приложение, называет оба.
|
|
131
|
+
- **`only` сильнее требования.** Ресурс, названный поимённо, ложится и при неотвеченном
|
|
132
|
+
требовании; перечень раскладки называет это вслух, а отказ по его пустому компаньону зовёт
|
|
133
|
+
снять ресурс, а не заполнять черновик.
|
|
134
|
+
- **Свойство, которого пакет не объявлял, роняет раскладку** — что в `has` дерева, что в имени
|
|
135
|
+
ресурса. Объявлены свойства перечнем при пакете, рядом с осями различия.
|
|
136
|
+
|
|
89
137
|
## Ловушки
|
|
90
138
|
|
|
91
139
|
- **Правила и паттерны при отвергнутом законе в отказе не перечисляются.** Их снимает каскад, а
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"db": {
|
|
3
|
+
"title": "хранилище: схема, миграции, записи предметной области"
|
|
4
|
+
},
|
|
5
|
+
"admin": {
|
|
6
|
+
"title": "админка: экраны правки записей и роли доступа"
|
|
7
|
+
},
|
|
8
|
+
"app": {
|
|
9
|
+
"title": "приложение: экраны, которыми пользуются люди"
|
|
10
|
+
},
|
|
11
|
+
"packages": {
|
|
12
|
+
"title": "публикуемые пакеты: реестр, версии, журнал изменений"
|
|
13
|
+
}
|
|
14
|
+
}
|
package/bin/agent-kit.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-kit.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/bin/agent-kit.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"agent-kit.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/bin/agent-kit.ts"],"names":[],"mappings":";AAeA,OAAO,EAAqC,iBAAiB,EAAqB,MAAM,oBAAoB,CAAC;AAqM7G,wBAAsB,IAAI,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAsE9E"}
|
package/bin/agent-kit.js
CHANGED
|
@@ -10,10 +10,12 @@ import { readFileSync } from 'node:fs';
|
|
|
10
10
|
import { dirname, join, resolve } from 'node:path';
|
|
11
11
|
import { fileURLToPath } from 'node:url';
|
|
12
12
|
import process from 'node:process';
|
|
13
|
+
import { unknownFlagsIn } from '../lib/argv.js';
|
|
13
14
|
import { readCatalog, resolveSelection } from '../lib/catalog.js';
|
|
14
|
-
import { adopt, doctor, init, list,
|
|
15
|
+
import { adopt, doctor, init, list, stats, sync } from '../lib/commands.js';
|
|
16
|
+
import { httpShip } from '../lib/ship.js';
|
|
17
|
+
import { propose } from '../lib/shipment.js';
|
|
15
18
|
import { DEFAULT_DAYS } from '../lib/observations.js';
|
|
16
|
-
import { ghIssue, repositoryOf } from '../lib/submit.js';
|
|
17
19
|
import { staleBuild } from '../lib/freshness.js';
|
|
18
20
|
import { packageRootFrom } from '../lib/package-root.js';
|
|
19
21
|
import { readAxes } from '../lib/variants.js';
|
|
@@ -29,7 +31,7 @@ const USAGE = [
|
|
|
29
31
|
' stats свести наблюдения: чем пользовались, чем ни разу, обо что спотыкались',
|
|
30
32
|
' stats --days N за сколько дней; без довода — за три',
|
|
31
33
|
' stats --json то же машиночитаемо — этим сводку прикладывают к предложению',
|
|
32
|
-
' propose отправить
|
|
34
|
+
' propose отправить груз в приём: сводку со снимком надстроек, предложения и разборы',
|
|
33
35
|
' propose --dry-run показать, что уехало бы, и ничего не отправлять',
|
|
34
36
|
' adopt [файлы] отдать пакету файлы, лежащие на его путях не от него',
|
|
35
37
|
'',
|
|
@@ -46,6 +48,17 @@ const USAGE = [
|
|
|
46
48
|
' --<ось> <вид> например `--host gitlab`; оси и виды — из `agent-kit list`',
|
|
47
49
|
' без флага спросить; без терминала — отказ, кроме `--all`',
|
|
48
50
|
];
|
|
51
|
+
/**
|
|
52
|
+
* Доводы отправки. Довод со значением помечен `<>`: за ним идёт отдельным словом путь, и без
|
|
53
|
+
* пометки этот путь читался бы как ещё один незнакомый довод.
|
|
54
|
+
*/
|
|
55
|
+
const PROPOSE_FLAGS = ['--dry-run', '--root <>'];
|
|
56
|
+
/** Что печатает отказ на незнакомом доводе: режимы команды, а не весь свод. */
|
|
57
|
+
const PROPOSE_USAGE = [
|
|
58
|
+
' propose отправить груз в приём',
|
|
59
|
+
' propose --dry-run показать, что уехало бы, и ничего не отправлять',
|
|
60
|
+
' --root <путь> корень проекта; по умолчанию текущий каталог',
|
|
61
|
+
];
|
|
49
62
|
/**
|
|
50
63
|
* Единственное место, где пакет узнаёт собственное расположение. `import.meta` живёт только
|
|
51
64
|
* здесь: библиотечные модули получают каталог ресурсов входным значением, и трансформ тестов,
|
|
@@ -61,9 +74,6 @@ function environmentOf(root) {
|
|
|
61
74
|
// Сверка со своими исходниками возможна только отсюда: здесь пакет знает, где лежит сам.
|
|
62
75
|
// У потребителя исходников рядом нет, и сверка молчит.
|
|
63
76
|
stale: staleBuild(pkg, manifest.name),
|
|
64
|
-
// Куда уезжают предложения. Читается из манифеста: зашитый в код адрес назвал бы чужое
|
|
65
|
-
// дерево в текстах пакета — и врал бы у всякого, кто пакет форкнул.
|
|
66
|
-
repository: repositoryOf(manifest.repository?.url ?? ''),
|
|
67
77
|
};
|
|
68
78
|
}
|
|
69
79
|
/** Чем это дерево себя выдаёт снаружи. Нет удалённого репозитория — нечем, и это не отказ. */
|
|
@@ -202,19 +212,24 @@ export async function main(argv) {
|
|
|
202
212
|
});
|
|
203
213
|
}
|
|
204
214
|
case 'propose': {
|
|
205
|
-
//
|
|
206
|
-
//
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
215
|
+
// Единственное действие этой команды необратимо и уходит наружу, поэтому незнакомый
|
|
216
|
+
// довод её кончает, а не пропускается молча: вызов ради списка режимов отправил в
|
|
217
|
+
// приём всё накопленное, и по выводу это не отличалось от «команда ничего не
|
|
218
|
+
// сделала». Прочие команды такого разбора не знают — их действие обратимо.
|
|
219
|
+
const unknown = unknownFlagsIn(argv.slice(1), PROPOSE_FLAGS);
|
|
220
|
+
if (unknown.length) {
|
|
221
|
+
return {
|
|
222
|
+
code: 1,
|
|
223
|
+
lines: [`таких доводов у \`propose\` нет: ${unknown.join(', ')}`, '', ...PROPOSE_USAGE],
|
|
224
|
+
};
|
|
225
|
+
}
|
|
212
226
|
return propose(env, {
|
|
213
227
|
dryRun: argv.includes('--dry-run'),
|
|
214
|
-
|
|
215
|
-
repository: env.repository ?? '',
|
|
228
|
+
ship: httpShip,
|
|
216
229
|
remote: remoteOf(env.root),
|
|
217
|
-
|
|
230
|
+
// Отрезок тот же, что у сводки по умолчанию: отправку зовут по свежей задаче.
|
|
231
|
+
days: DEFAULT_DAYS,
|
|
232
|
+
today: new Date().toISOString().slice(0, 10),
|
|
218
233
|
});
|
|
219
234
|
}
|
|
220
235
|
case 'doctor':
|