@rt-tools/agent-kit 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/checks/check-file-size.mjs +19 -4
- package/assets/checks/check-state-next.mjs +10 -2
- package/assets/checks/rt-kit-checks.config.mjs +16 -2
- package/assets/defaults/project.sh +9 -1
- package/assets/defaults/turn-map.md +8 -6
- package/assets/hooks/browser-guard-device-id.sh +3 -1
- package/assets/hooks/browser-guard-no-asking.sh +3 -1
- package/assets/hooks/browser-guard-no-other-drivers.sh +5 -3
- package/assets/hooks/browser-guard-require-select.sh +4 -2
- package/assets/hooks/claim-guard.sh +3 -1
- package/assets/hooks/conscience-guard.sh +3 -1
- package/assets/hooks/dev-server-guard.sh +5 -3
- package/assets/hooks/dispatch.sh +69 -0
- package/assets/hooks/docs-guard.sh +6 -4
- package/assets/hooks/exam-guard.sh +5 -3
- package/assets/hooks/git-guard-delivery.sh +37 -5
- package/assets/hooks/git-guard-main.sh +6 -4
- package/assets/hooks/git-guard-push-tests.sh +6 -4
- package/assets/hooks/grill-gate.sh +4 -2
- package/assets/hooks/handoff-entry-guard.sh +4 -2
- package/assets/hooks/handoff-write.sh +27 -6
- package/assets/hooks/hook-input.sh +54 -0
- package/assets/hooks/lint-after-edit.sh +5 -3
- package/assets/hooks/postmortem-guard.sh +3 -1
- package/assets/hooks/proposal-guard.sh +3 -1
- package/assets/hooks/prose-style-guard.sh +5 -3
- package/assets/hooks/qa-dataid-guard.sh +4 -2
- package/assets/hooks/rerun-guard.sh +5 -3
- package/assets/hooks/reuse-first-guard.sh +5 -3
- package/assets/hooks/rule-article.sh +99 -0
- package/assets/hooks/skill-gate-rearm.sh +3 -1
- package/assets/hooks/skill-gate.sh +23 -2
- package/assets/hooks/skill-loaded.sh +3 -1
- package/assets/hooks/sql-guard-request.sh +2 -1
- package/assets/hooks/sql-guard.sh +4 -2
- package/assets/hooks/task-flow-guard.sh +6 -4
- package/assets/hooks/turn-exit-guard.sh +42 -17
- package/assets/hooks/waiting-turn-guard.sh +3 -1
- package/assets/hooks/window-fill-guard.sh +6 -4
- package/assets/laws/work-conduct.md +5 -9
- package/assets/patterns/dependencies-upgrade.md +1 -1
- package/assets/patterns/doc-style-write.md +3 -3
- package/assets/patterns/git-workflow-commit.azure.md +2 -202
- package/assets/patterns/git-workflow-commit.github.md +2 -258
- package/assets/patterns/git-workflow-commit.gitlab.md +1 -217
- package/assets/patterns/git-workflow-docker.md +3 -3
- package/assets/patterns/git-workflow-merge.md +3 -2
- package/assets/patterns/git-workflow-migration.md +3 -3
- package/assets/patterns/git-workflow-pr.azure.md +224 -0
- package/assets/patterns/git-workflow-pr.github.md +280 -0
- package/assets/patterns/git-workflow-pr.gitlab.md +240 -0
- package/assets/patterns/git-workflow-restart.md +3 -3
- package/assets/patterns/git-workflow-secrets.md +3 -3
- package/assets/patterns/task-flow-archive.md +193 -0
- package/assets/patterns/task-flow-close.md +3 -173
- package/assets/patterns/task-flow-handoff.md +4 -4
- package/assets/pitfalls/doc-style.md +80 -0
- package/assets/pitfalls/git-workflow.azure.md +50 -0
- package/assets/pitfalls/git-workflow.github.md +78 -0
- package/assets/pitfalls/git-workflow.gitlab.md +49 -0
- package/assets/pitfalls/spec-driven.md +36 -0
- package/assets/pitfalls/styling-bem.md +45 -0
- package/assets/pitfalls/task-flow.md +62 -0
- package/assets/pitfalls/testing.md +70 -0
- package/assets/rules/deploy-flow.azure.md +106 -0
- package/assets/rules/deploy-flow.github.md +113 -0
- package/assets/rules/deploy-flow.gitlab.md +108 -0
- package/assets/rules/doc-style.md +25 -76
- package/assets/rules/git-workflow.azure.md +6 -92
- package/assets/rules/git-workflow.github.md +14 -127
- package/assets/rules/git-workflow.gitlab.md +6 -93
- package/assets/rules/spec-driven.md +39 -30
- package/assets/rules/styling-bem.md +20 -39
- package/assets/rules/task-flow.md +17 -199
- package/assets/rules/testing.md +3 -64
- package/assets/rules/turn-conduct.md +206 -0
- package/assets/rules/typescript-conventions.md +15 -0
- package/assets/skills/agent-kit.md +35 -12
- package/assets/templates/pitfalls.md +10 -0
- package/assets/templates/rule.md +5 -3
- package/bin/agent-kit.d.ts.map +1 -1
- package/bin/agent-kit.js +1 -42
- package/bin/agent-kit.js.map +1 -1
- package/lib/assets.d.ts.map +1 -1
- package/lib/assets.js +6 -1
- package/lib/assets.js.map +1 -1
- package/lib/cascade.d.ts.map +1 -1
- package/lib/cascade.js +19 -1
- package/lib/cascade.js.map +1 -1
- package/lib/commands.d.ts.map +1 -1
- package/lib/commands.js +1 -0
- package/lib/commands.js.map +1 -1
- package/lib/config.d.ts +16 -1
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js +8 -0
- package/lib/config.js.map +1 -1
- package/lib/hooks-map.d.ts +13 -0
- package/lib/hooks-map.d.ts.map +1 -1
- package/lib/hooks-map.js +33 -1
- package/lib/hooks-map.js.map +1 -1
- package/lib/ship.d.ts +1 -2
- package/lib/ship.d.ts.map +1 -1
- package/lib/ship.js +0 -54
- package/lib/ship.js.map +1 -1
- package/package.json +1 -1
- package/rt-tools-agent-kit-0.12.0.tgz +0 -0
- package/assets/commands/agent-kit-digest.md +0 -89
- package/assets/commands/rules-review.md +0 -98
- package/assets/patterns/cargo-triage-mark.md +0 -119
- package/assets/rules/cargo-triage.md +0 -126
- package/lib/cargo-state.d.ts +0 -62
- package/lib/cargo-state.d.ts.map +0 -1
- package/lib/cargo-state.js +0 -118
- package/lib/cargo-state.js.map +0 -1
- package/rt-tools-agent-kit-0.11.0.tgz +0 -0
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Смысловое ревью семьи текстов слоя правил — закон, его правила и паттерны при них
|
|
3
|
-
argument-hint: '<имя закона>'
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
Прогони смысловое ревью одной семьи текстов пакета правил. Семья: `$ARGUMENTS`
|
|
7
|
-
|
|
8
|
-
Зовётся **в репозитории самого пакета**, а не в дереве, где он стоит: судятся исходные тексты
|
|
9
|
-
ресурсов, и лежат они только здесь. В чужом дереве лежит разложенная копия выбранных ресурсов, а
|
|
10
|
-
не семья целиком, и путей, по которым команда ходит, в нём нет вовсе: обход по ним вернёт
|
|
11
|
-
пустоту, неотличимую от «такого закона не бывает». Каталог ресурсов ниже назван так, как он
|
|
12
|
-
зовётся в репозитории пакета.
|
|
13
|
-
|
|
14
|
-
Считаемое ловит проверка полноты текстов — недостающий раздел, правило без паттерна, имя соседа,
|
|
15
|
-
которому в наборе ничего не отвечает. Здесь ищется то, чего она не считает: два текста,
|
|
16
|
-
говорящих об одном разное, и случай, которого не назвал ни один. Ответ роли не повторяется от
|
|
17
|
-
запуска к запуску, поэтому в гейт он не идёт и ветку не отбивает.
|
|
18
|
-
|
|
19
|
-
## 1. Пойми, какая семья
|
|
20
|
-
|
|
21
|
-
Семья зовётся именем закона — без пути и без расширения: `work-conduct`, `delivery`,
|
|
22
|
-
`project-documentation`.
|
|
23
|
-
|
|
24
|
-
```bash
|
|
25
|
-
ls projects/agent-kit/assets/laws/*.md projects/agent-kit/assets/laws/*/*.md
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
**Имени нет** — назови человеку перечень имён и остановись. Догадываться по похожести нельзя:
|
|
29
|
-
ревью уйдёт на чужую семью, и его находки человек примет за находки о своей.
|
|
30
|
-
|
|
31
|
-
**Названо несколько** — гони по одной, по очереди, и ответы не смешивай: находка семьи читается
|
|
32
|
-
вместе с её законом, а сваленные в кучу они теряют адрес.
|
|
33
|
-
|
|
34
|
-
**Довода нет вовсе** — потребуй имя и напечатай перечень. Умолчания здесь нет: «первый
|
|
35
|
-
попавшийся закон» даёт прогон, неотличимый от осмысленного.
|
|
36
|
-
|
|
37
|
-
**Закон лежит в слое приложения** — это законный случай, а не промах: у денег, локалей и доступа
|
|
38
|
-
семья такая же. Читается он оттуда же, где лежит.
|
|
39
|
-
|
|
40
|
-
## 2. Собери семью
|
|
41
|
-
|
|
42
|
-
Правило принадлежит закону полем `law:`, паттерн правилу — полем `rule:`. Приставка имени
|
|
43
|
-
ненадёжна: её несут не все паттерны.
|
|
44
|
-
|
|
45
|
-
```bash
|
|
46
|
-
LAW=<имя закона>
|
|
47
|
-
grep -l "^law: $LAW\$" projects/agent-kit/assets/rules/*.md
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
Дальше по каждому найденному правилу — его паттерны. Имя правила для поиска берётся голым: без
|
|
51
|
-
вида и без требования — оба стоят суффиксами в имени файла, а поле `rule:` у паттерна несёт
|
|
52
|
-
только само имя.
|
|
53
|
-
|
|
54
|
-
```bash
|
|
55
|
-
RULE=<имя правила: первое слово имени файла, до первой точки>
|
|
56
|
-
grep -l "^rule: $RULE\$" projects/agent-kit/assets/patterns/*.md
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
**Виды берутся все.** `git-workflow.github`, `git-workflow.gitlab`, `git-workflow.azure` — три
|
|
60
|
-
редакции одного правила: дерево раскладывает одну, а расходятся они молча.
|
|
61
|
-
|
|
62
|
-
**Суффикс требования — не вид.** `entity-conventions.needs-admin`, `observability.needs-app` —
|
|
63
|
-
это правила, которые дерево берёт, только когда объявило нужную черту. Имя с этим суффиксом в
|
|
64
|
-
поле `rule:` не стоит ни у одного паттерна: поиск по нему возвращает пустоту, и семья уезжает в
|
|
65
|
-
ревью без паттернов вовсе — молча, потому что пустой ответ выглядит как «паттернов нет».
|
|
66
|
-
|
|
67
|
-
**У закона нет ни одного правила** — скажи это человеку и остановись. Читать один закон нечем:
|
|
68
|
-
расхождение живёт между двумя текстами, а пробел уровня статьи без правил под ней — не находка
|
|
69
|
-
ревью, а отсутствие целого слоя. Сам по себе такой закон стоит разговора: его находит и проверка
|
|
70
|
-
полноты текстов, и она же скажет, сколько их.
|
|
71
|
-
|
|
72
|
-
## 3. Запусти роль
|
|
73
|
-
|
|
74
|
-
Инструментом `Agent`, `subagent_type: 'rules-reviewer'`. В промпт — имя закона и полный список
|
|
75
|
-
путей: закон, все его правила со всеми видами, все паттерны при них. Список собираешь ты: роль
|
|
76
|
-
git-команд не зовёт и историю не читает.
|
|
77
|
-
|
|
78
|
-
Одна роль на семью. Веер из нескольких ролей со сведением ответов здесь не заводится: взгляд на
|
|
79
|
-
предмет один — два текста об одном говорят разное, — а сведение превращает дословные цитаты в
|
|
80
|
-
пересказ.
|
|
81
|
-
|
|
82
|
-
## 4. Покажи находки человеку
|
|
83
|
-
|
|
84
|
-
**Как есть.** Роль возвращает цитаты дословно, и пересказ их портит: по пересказу человек не
|
|
85
|
-
отличит настоящее расхождение от прочтения роли.
|
|
86
|
-
|
|
87
|
-
Порядок сохрани: сперва расхождения — у каждого два места и две цитаты, — потом пробелы, у
|
|
88
|
-
которых второго места нет.
|
|
89
|
-
|
|
90
|
-
По каждой находке скажи своё: согласен или нет и почему. Правку не вноси — тексты правил
|
|
91
|
-
действуют на все будущие сессии всех деревьев, и решает по ним человек.
|
|
92
|
-
|
|
93
|
-
Находка, с которой человек согласился, идёт дальше двумя путями, и выбирает он:
|
|
94
|
-
|
|
95
|
-
- **правится тут же** — если это правка текста пакета и она укладывается в текущую работу;
|
|
96
|
-
- **уходит задачей** в очередь работ — если тянет за собой код, раскладку или другой закон.
|
|
97
|
-
|
|
98
|
-
Пустой ответ роли — тоже результат: скажи, что находок нет, и не выдумывай их из вежливости.
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: cargo-triage-mark
|
|
3
|
-
kind: pattern
|
|
4
|
-
rule: cargo-triage
|
|
5
|
-
description: Паттерн правила cargo-triage. Брать при разборе приехавшего груза — готовые вызовы отметки: сухой прогон, пачка записей за вызов, приём починки при переходе в готово, версия выпуска при выпуске, разбор отбитой строки. Не брать для сведения предложений в правки пакета — это своя команда.
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Отметка записей груза
|
|
9
|
-
|
|
10
|
-
Паттерн правила `cargo-triage`. Что при этом должно быть верно — закон
|
|
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
|
-
`implementation.md` правила. Ниже они стоят так, как их зовёт пакет.
|
|
31
|
-
|
|
32
|
-
## Взятие в работу: задача и отметка одним ходом
|
|
33
|
-
|
|
34
|
-
Сначала задача — иначе отметка говорит, что запись взяли, и молчит о том, где идёт работа:
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
npm run task:new -- --title '<что не так>' --slug <короткое-имя> --label bug < тело.md
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
Отметка идёт следом, тем же ходом, и несёт все записи, которые эта задача закрывает:
|
|
41
|
-
|
|
42
|
-
```bash
|
|
43
|
-
npx agent-kit mark --state in_work \
|
|
44
|
-
--postmortem 2026-08-14-structure-invented-beside-the-sample.md \
|
|
45
|
-
--postmortem 2026-08-15-guard-denied-shell-wrote-anyway.md \
|
|
46
|
-
--proposal <признак предложения>
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
Род записи называется своим доводом: разбор происшествия — именем файла, предложение —
|
|
50
|
-
признаком текста. Записи обоих родов едут одним вызовом.
|
|
51
|
-
|
|
52
|
-
Сухим прогоном смотрят, что уехало бы, — он ничего не отправляет и следа наружу не оставляет:
|
|
53
|
-
|
|
54
|
-
```bash
|
|
55
|
-
npx agent-kit mark --state in_work --postmortem <файл> --dry-run
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
Сухой прогон вместо настоящего вызова оставляет запись в прежнем состоянии. Отметкой он не
|
|
59
|
-
считается.
|
|
60
|
-
|
|
61
|
-
## Починка: переход вместе с ответом на «чем»
|
|
62
|
-
|
|
63
|
-
Ставится после того, как правка влита в главную ветку, — не по открытой заявке:
|
|
64
|
-
|
|
65
|
-
```bash
|
|
66
|
-
npx agent-kit mark --state fixed \
|
|
67
|
-
--postmortem <файл> \
|
|
68
|
-
--fix 'заведена статья правила о разборе груза и паттерн с готовыми вызовами'
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
Текст отвечает на «чем», а не на «где»: статья правила, гард, проверка, правка кода. Без него
|
|
72
|
-
строка отбивается — переход в починку без ответа на «чем» приёмник не принимает.
|
|
73
|
-
|
|
74
|
-
## Выпуск: версия называется тем, кто публикует
|
|
75
|
-
|
|
76
|
-
Идёт тем же движением, что и публикация редакции:
|
|
77
|
-
|
|
78
|
-
```bash
|
|
79
|
-
npx agent-kit mark --state released --postmortem <файл> --release 'rt-agent-kit@0.10.1'
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
Версия — та, которой назван выпуск, увёзший починку. Не номер редакции приёмника и не время
|
|
83
|
-
выкатки.
|
|
84
|
-
|
|
85
|
-
## Ответ читается
|
|
86
|
-
|
|
87
|
-
Вызов отвечает тремя числами и списком:
|
|
88
|
-
|
|
89
|
-
```
|
|
90
|
-
переведено 2, уже стояло 1, отбито 1
|
|
91
|
-
строка 3: <ключ> — записи у дерева нет
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
- **Переведено 0, уже стояло N** — этот разбор не двинул ничего: записи отмечены раньше либо
|
|
95
|
-
ключи названы не те.
|
|
96
|
-
- **Отбито N** — эти записи остались там, где были. Причина названа при строке, и повтор того
|
|
97
|
-
же вызова отбивается ровно так же.
|
|
98
|
-
|
|
99
|
-
Причины отбоя и что делать с каждой:
|
|
100
|
-
|
|
101
|
-
| Что сказано | Что это значит | Что делать |
|
|
102
|
-
| ---------------------- | ---------------------------------------------- | ------------------------------------ |
|
|
103
|
-
| записи у дерева нет | ключ назван не тот либо запись прислало не оно | сверить ключ со списком в админке |
|
|
104
|
-
| переход не разрешён | шаг через состояние либо ход назад | пройти состояние, которое пропустили |
|
|
105
|
-
| перехода без текста | починка без ответа на «чем» | добавить довод с текстом починки |
|
|
106
|
-
| текста не при том шаге | текст приехал с переходом, который не починка | убрать довод либо сменить состояние |
|
|
107
|
-
| перехода без версии | выпуск без ответа на «где искать фикс» | добавить довод с версией выпуска |
|
|
108
|
-
| версии не при том шаге | версия приехала с переходом, который не выпуск | убрать довод либо сменить состояние |
|
|
109
|
-
|
|
110
|
-
## Ловушки
|
|
111
|
-
|
|
112
|
-
- **Вызов без токена отбивается без сети.** Токен лежит вне дерева, и на свежей рабочей копии
|
|
113
|
-
его нет: команда называет это прямо, а не молчит.
|
|
114
|
-
- **Своё дерево называется признаком из токена, а не доводом.** Приём сверяет его сам, и
|
|
115
|
-
назваться чужим деревом вызов не может.
|
|
116
|
-
- **Записи, отмеченные в одной ветке, в соседней выглядят неотмеченными только в файлах.**
|
|
117
|
-
Состояние лежит в приёме, а не в дереве: смотрят его в админке, а не в рабочей копии.
|
|
118
|
-
- **Повторная отметка тем же состоянием промахом не считается.** Рабочий порядок повторяют, и
|
|
119
|
-
вторая та же отметка отбивается ответом «уже стояло», а не отказом.
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: cargo-triage
|
|
3
|
-
kind: rule
|
|
4
|
-
law: work-conduct
|
|
5
|
-
description: Правило под «Закон о ведении работы». Брать, когда разбирается груз, приехавший в приём, — разборы происшествий и предложения от деревьев. Называет, чем груз читается, что значит взять отчёт в работу и когда у записи появляются отметки о починке и о выпуске. Готовые вызовы — в паттерне cargo-triage-mark.
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Разбор приехавшего груза — как это устроено здесь
|
|
9
|
-
|
|
10
|
-
Правило под закон `docs/constitution/work-conduct.md`. Закон говорит, что работа ведётся так,
|
|
11
|
-
чтобы её состояние переживало заход; здесь — как это держится для чужой работы, приехавшей
|
|
12
|
-
грузом. Своя работа идёт правилом `task-flow` под тем же законом, и одно продолжает другое:
|
|
13
|
-
взятие отчёта в работу заводит задачу, а с задачи начинается тот ход.
|
|
14
|
-
|
|
15
|
-
## Как это называется здесь
|
|
16
|
-
|
|
17
|
-
| В законе | Здесь |
|
|
18
|
-
| -------------------------------------- | --------------------------------------------------------------------------- |
|
|
19
|
-
| работа, о которой сказал кто-то другой | груз: разбор происшествия и предложение, приехавшие в приём от дерева |
|
|
20
|
-
| состояние работы, пережившее заход | состояние записи груза: новое, в работе, готово, выпущено |
|
|
21
|
-
| отметка о сделанном | вызов команды отметки — она переводит записи и пишет приём починки и версию |
|
|
22
|
-
| место, где состояние читают | админка приёма: столбец состояния, отбор по нему и панель записи |
|
|
23
|
-
| ответ на «чем исправлено» | приём починки: статья правила, гард, проверка, правка кода |
|
|
24
|
-
| ответ на «где искать фикс» | версия выпуска: строка, которой дерево назвало выпуск |
|
|
25
|
-
|
|
26
|
-
## Где это лежит
|
|
27
|
-
|
|
28
|
-
В этом дереве — таблица в `implementation.md` рядом: адрес приёма, чем зовётся команда отметки
|
|
29
|
-
и как называются состояния в её доводах. Пути живут там, а не здесь: правило переносится между
|
|
30
|
-
репозиториями, а адрес приёма и имя команды у каждого дерева свои.
|
|
31
|
-
|
|
32
|
-
## Ход
|
|
33
|
-
|
|
34
|
-
Ход одной записи груза от приезда до выпуска: где ставится каждая отметка и что делается
|
|
35
|
-
раньше неё.
|
|
36
|
-
|
|
37
|
-
```mermaid
|
|
38
|
-
flowchart TD
|
|
39
|
-
A[Запись груза приехала в приём] --> B[Список сужается отбором по «новое» и идёт порядком приезда]
|
|
40
|
-
B --> C{Работа по записи будет}
|
|
41
|
-
C -->|Нет| D[Состояние не двигается: состояния отказа набором не заведено]
|
|
42
|
-
C -->|Да| E[Заводится задача, и тем же ходом запись переводится в «в работе»]
|
|
43
|
-
E --> F[Работа идёт обычным ходом: ветка, папка задачи, замысел]
|
|
44
|
-
F --> G{Правка влита в главную ветку}
|
|
45
|
-
G -->|Нет| F
|
|
46
|
-
G -->|Да| H[Запись переводится в «готово», и с переходом едет приём починки]
|
|
47
|
-
H --> I{Редакция с починкой опубликована}
|
|
48
|
-
I -->|Нет| I
|
|
49
|
-
I -->|Да| J[Публикующий переводит запись в «выпущено» и называет версию]
|
|
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
|
-
её не считают. Без текста переход отбивается построчно — список снова показал бы состояние,
|
|
75
|
-
у которого нет ответа на «чем».
|
|
76
|
-
- **«Выпущено» ставится тем, кто публикует редакцию, и тем же движением, что и публикация.**
|
|
77
|
-
У него версия под рукой; отложенный до следующего захода выпуск отмечается по памяти или не
|
|
78
|
-
отмечается вовсе.
|
|
79
|
-
- **Между «готово» и «выпущено» стоит редакция.** Потребитель получает фикс только после
|
|
80
|
-
раскладки у себя, и два состояния разведены ровно поэтому.
|
|
81
|
-
- **Отметка ставится командой, а не рукой человека в админке.** Правка закрыта токеном дерева:
|
|
82
|
-
человек груз читает, а разбирает его тот, кто по нему работает.
|
|
83
|
-
- **Записи всего разбора едут одной пачкой.** Команда принимает несколько записей за вызов, и
|
|
84
|
-
вызов на каждую стоил бы столько же, сколько сам разбор.
|
|
85
|
-
- **Ответ команды читается, а не подразумевается.** Он называет, сколько записей переведено,
|
|
86
|
-
сколько уже стояло в названном состоянии и какие строки отбиты. Отбитая строка означает, что
|
|
87
|
-
запись осталась там, где была, и разбирается она причиной отбоя, а не повтором того же
|
|
88
|
-
вызова.
|
|
89
|
-
- **Разбор груза и сведение предложений — два разных шага.** Сведение делит пришедшее на
|
|
90
|
-
повторившееся и разовое и решает, что становится правкой; разбор груза отмечает состояние
|
|
91
|
-
каждой записи. Сведение зовут раз в несколько дней по отрезку, разбор — всякий раз, когда
|
|
92
|
-
работу берут.
|
|
93
|
-
|
|
94
|
-
## Чего из закона здесь нет
|
|
95
|
-
|
|
96
|
-
Ничего из перечисленного не проверяет машина, и проверки на это не будет: разбор груза
|
|
97
|
-
исполняет агент, и признака «прочитал и решил» у него нет. Гард видел бы только вызов команды,
|
|
98
|
-
а вызов без разбора ничем не отличается от вызова после него.
|
|
99
|
-
|
|
100
|
-
Держится правило двумя вещами, и обе видны в самом приёме. Первая — запись, у которой правка
|
|
101
|
-
влита, а состояние прежнее: она называет пропущенный шаг сама, как только на список посмотрят
|
|
102
|
-
отбором. Вторая — число записей в «новом»: растущее означает, что разбор не идёт вовсе.
|
|
103
|
-
|
|
104
|
-
Запись, по которой работы не будет, отметить нечем: состояния отказа набор не знает. «Новое»
|
|
105
|
-
оставляет её среди неразобранных навсегда, «в работе» лжёт. Это открытый вопрос договорённости,
|
|
106
|
-
а не умолчание правила: разбирается такая запись каждый раз заново, пока владелец не решил.
|
|
107
|
-
|
|
108
|
-
## Паттерны
|
|
109
|
-
|
|
110
|
-
- `cargo-triage-mark` — готовые вызовы: сухой прогон, отметка пачкой, приём починки и версия
|
|
111
|
-
выпуска, разбор отбитой строки.
|
|
112
|
-
|
|
113
|
-
## Ловушки
|
|
114
|
-
|
|
115
|
-
- **Отметка, отложенная «на потом», не ставится.** Между решением и следующим ходом проходит
|
|
116
|
-
день, и запись груза к этому дню помнит только приём. Отмечают тем же ходом, которым решили.
|
|
117
|
-
- **Сухой прогон отметкой не считается.** Он показывает, что уехало бы, и следа наружу не
|
|
118
|
-
оставляет: запись остаётся в прежнем состоянии, а исполнитель уходит с ощущением сделанного.
|
|
119
|
-
- **«Готово» по открытой заявке — отметка о том, чего в дереве нет.** Между открытием и
|
|
120
|
-
слиянием проходит день и больше, а заявку ещё и закрывают без слияния.
|
|
121
|
-
- **Приём починки, написанный пересказом разбора, отвечает не на тот вопрос.** Запись груза уже
|
|
122
|
-
несёт то, что было не так; отметка говорит, что с этим сделали, — и читают её как раз затем,
|
|
123
|
-
чтобы понять, стоит ли чинить у себя.
|
|
124
|
-
- **Ответ команды с нулём переведённых читается как отказ, а не как успех.** Строка «переведено
|
|
125
|
-
0, уже стояло 3» означает, что этот разбор не двинул ничего: либо записи отмечены раньше,
|
|
126
|
-
либо ключи названы не те.
|
package/lib/cargo-state.d.ts
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Отметка состояния груза: команда, которой исполнитель двигает свои записи в приёме.
|
|
3
|
-
*
|
|
4
|
-
* Разбор доводов и сборка пакета отделены от самого запроса нарочно — тем же приёмом, что и
|
|
5
|
-
* отправка груза: спека подставляет двойник вызова и никуда не стучится, а всё, что можно
|
|
6
|
-
* отбить до сети, отбивается до сети. Незнакомое состояние и вызов без записей — промахи
|
|
7
|
-
* исполнителя, и запрос по ним не уходит вовсе.
|
|
8
|
-
*/
|
|
9
|
-
import { ICargoStateAccepted, ICargoStateBody, ICargoStateItem } from './cargo.js';
|
|
10
|
-
import { IOutcomeOfCommand } from './commands.js';
|
|
11
|
-
/** Довод, которым называется разбор происшествия. */
|
|
12
|
-
export declare const POSTMORTEM_FLAG: string;
|
|
13
|
-
/** Довод, которым называется предложение. */
|
|
14
|
-
export declare const PROPOSAL_FLAG: string;
|
|
15
|
-
/** Довод текста починки: чем недочёт исправлен. */
|
|
16
|
-
export declare const FIX_FLAG: string;
|
|
17
|
-
/**
|
|
18
|
-
* Довод версии выпуска: в какой версии искать фикс.
|
|
19
|
-
*
|
|
20
|
-
* Назван по выпуску, а не по версии: `--version` у команды строки запуска читается как «покажи
|
|
21
|
-
* свою версию», и заняв его под другое, пакет получил бы две разные вещи под одним словом.
|
|
22
|
-
*/
|
|
23
|
-
export declare const RELEASE_FLAG: string;
|
|
24
|
-
/** Что приём ответил на правку состояния. Отказ — такой же ответ, как принятое. */
|
|
25
|
-
export interface IMarked {
|
|
26
|
-
readonly ok: boolean;
|
|
27
|
-
/** Код ответа. Ноль — приём не ответил вовсе: не дозвонились, оборвалось, вышло время. */
|
|
28
|
-
readonly status: number;
|
|
29
|
-
readonly said: string;
|
|
30
|
-
/** Ответ приёма. Пусто у отказа: два числа и отбитые строки он называет только у принятого. */
|
|
31
|
-
readonly accepted: ICargoStateAccepted | null;
|
|
32
|
-
}
|
|
33
|
-
/** Чем отметка ходит в приём. Двойник в спеке — того же вида. */
|
|
34
|
-
export type TMarkCall = (intake: string, token: string, body: ICargoStateBody) => Promise<IMarked>;
|
|
35
|
-
/** Приложенные к строке значения: что едет вместе с состоянием. */
|
|
36
|
-
export interface ICargoStateAttached {
|
|
37
|
-
/** Чем недочёт исправлен. Пустая строка — довода не было. */
|
|
38
|
-
readonly fixNote: string;
|
|
39
|
-
/** В какой версии искать фикс. Пустая строка — довода не было. */
|
|
40
|
-
readonly releaseVersion: string;
|
|
41
|
-
}
|
|
42
|
-
/** Всё, что отметке нужно знать: куда, чем представиться и что отмечать. */
|
|
43
|
-
export interface IMarkOptions {
|
|
44
|
-
readonly intake: string;
|
|
45
|
-
readonly tree: string;
|
|
46
|
-
readonly token: string;
|
|
47
|
-
readonly state: string;
|
|
48
|
-
readonly items: readonly ICargoStateItem[];
|
|
49
|
-
readonly dryRun: boolean;
|
|
50
|
-
readonly call: TMarkCall;
|
|
51
|
-
}
|
|
52
|
-
/** Записи, названные доводами строки запуска: род у каждой свой, порядок — как их назвали. */
|
|
53
|
-
export declare function itemsOf(argv: readonly string[], state: string, attached?: ICargoStateAttached): readonly ICargoStateItem[];
|
|
54
|
-
/**
|
|
55
|
-
* Отметить записи дерева названным состоянием.
|
|
56
|
-
*
|
|
57
|
-
* Порядок отказов не случаен: сперва то, что видно без сети, — незнакомое состояние, пустой
|
|
58
|
-
* вызов, отсутствующий токен, — и только потом запрос. Холостой ход стоит последним из них:
|
|
59
|
-
* он показывает собранный пакет, а собрать его можно лишь после того, как доводы сошлись.
|
|
60
|
-
*/
|
|
61
|
-
export declare function mark(options: IMarkOptions): Promise<IOutcomeOfCommand>;
|
|
62
|
-
//# sourceMappingURL=cargo-state.d.ts.map
|
package/lib/cargo-state.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cargo-state.d.ts","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/cargo-state.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAsC,mBAAmB,EAAE,eAAe,EAAE,eAAe,EAAmB,MAAM,YAAY,CAAC;AACxI,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAKlD,qDAAqD;AACrD,eAAO,MAAM,eAAe,EAAE,MAAuB,CAAC;AAEtD,6CAA6C;AAC7C,eAAO,MAAM,aAAa,EAAE,MAAqB,CAAC;AAElD,mDAAmD;AACnD,eAAO,MAAM,QAAQ,EAAE,MAAgB,CAAC;AAExC;;;;;GAKG;AACH,eAAO,MAAM,YAAY,EAAE,MAAoB,CAAC;AAEhD,mFAAmF;AACnF,MAAM,WAAW,OAAO;IACpB,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,0FAA0F;IAC1F,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,+FAA+F;IAC/F,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,GAAG,IAAI,CAAC;CACjD;AAED,iEAAiE;AACjE,MAAM,MAAM,SAAS,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAEnG,mEAAmE;AACnE,MAAM,WAAW,mBAAmB;IAChC,6DAA6D;IAC7D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,kEAAkE;IAClE,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACnC;AAED,4EAA4E;AAC5E,MAAM,WAAW,YAAY;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,SAAS,eAAe,EAAE,CAAC;IAC3C,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;CAC5B;AAWD,8FAA8F;AAC9F,wBAAgB,OAAO,CACnB,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,KAAK,EAAE,MAAM,EACb,QAAQ,GAAE,mBAAyD,GACpE,SAAS,eAAe,EAAE,CAsB5B;AA+BD;;;;;;GAMG;AACH,wBAAsB,IAAI,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAgD5E"}
|
package/lib/cargo-state.js
DELETED
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Отметка состояния груза: команда, которой исполнитель двигает свои записи в приёме.
|
|
3
|
-
*
|
|
4
|
-
* Разбор доводов и сборка пакета отделены от самого запроса нарочно — тем же приёмом, что и
|
|
5
|
-
* отправка груза: спека подставляет двойник вызова и никуда не стучится, а всё, что можно
|
|
6
|
-
* отбить до сети, отбивается до сети. Незнакомое состояние и вызов без записей — промахи
|
|
7
|
-
* исполнителя, и запрос по ним не уходит вовсе.
|
|
8
|
-
*/
|
|
9
|
-
import { CARGO_SCHEMA_VERSION, CARGO_STATES } from './cargo.js';
|
|
10
|
-
/** Код возврата у всего, что не легло: отбитая строка кончает команду ненулевым кодом. */
|
|
11
|
-
const REFUSED = 1;
|
|
12
|
-
/** Довод, которым называется разбор происшествия. */
|
|
13
|
-
export const POSTMORTEM_FLAG = '--postmortem';
|
|
14
|
-
/** Довод, которым называется предложение. */
|
|
15
|
-
export const PROPOSAL_FLAG = '--proposal';
|
|
16
|
-
/** Довод текста починки: чем недочёт исправлен. */
|
|
17
|
-
export const FIX_FLAG = '--fix';
|
|
18
|
-
/**
|
|
19
|
-
* Довод версии выпуска: в какой версии искать фикс.
|
|
20
|
-
*
|
|
21
|
-
* Назван по выпуску, а не по версии: `--version` у команды строки запуска читается как «покажи
|
|
22
|
-
* свою версию», и заняв его под другое, пакет получил бы две разные вещи под одним словом.
|
|
23
|
-
*/
|
|
24
|
-
export const RELEASE_FLAG = '--release';
|
|
25
|
-
/** Род записи по доводу, которым её назвали. Не наш довод — пусто. */
|
|
26
|
-
function kindOfFlag(flag) {
|
|
27
|
-
if (flag === POSTMORTEM_FLAG) {
|
|
28
|
-
return 'postmortem';
|
|
29
|
-
}
|
|
30
|
-
return flag === PROPOSAL_FLAG ? 'proposal' : null;
|
|
31
|
-
}
|
|
32
|
-
/** Записи, названные доводами строки запуска: род у каждой свой, порядок — как их назвали. */
|
|
33
|
-
export function itemsOf(argv, state, attached = { fixNote: '', releaseVersion: '' }) {
|
|
34
|
-
const items = [];
|
|
35
|
-
for (let at = 0; at < argv.length; at += 1) {
|
|
36
|
-
const kind = kindOfFlag(argv[at]);
|
|
37
|
-
const key = argv[at + 1] ?? '';
|
|
38
|
-
if (kind && key && !key.startsWith('--')) {
|
|
39
|
-
// Приложенное значение едет полем строки, а не своим вызовом: отметка одна, и все её
|
|
40
|
-
// записи чинились одним разбором либо уехали одним выпуском — второго значения на
|
|
41
|
-
// тот же вызов не задаётся
|
|
42
|
-
items.push({
|
|
43
|
-
kind,
|
|
44
|
-
key,
|
|
45
|
-
state,
|
|
46
|
-
...(attached.fixNote ? { fixNote: attached.fixNote } : {}),
|
|
47
|
-
...(attached.releaseVersion ? { releaseVersion: attached.releaseVersion } : {}),
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
return items;
|
|
52
|
-
}
|
|
53
|
-
/** Отказ строками. */
|
|
54
|
-
function refusal(...lines) {
|
|
55
|
-
return { code: REFUSED, lines: [...lines] };
|
|
56
|
-
}
|
|
57
|
-
/** Пакет одной строкой: её читает человек перед тем, как отправить. */
|
|
58
|
-
function describe(items, state) {
|
|
59
|
-
const postmortems = items.filter((one) => one.kind === 'postmortem').length;
|
|
60
|
-
return `в «${state}»: разборов ${postmortems}, предложений ${items.length - postmortems}`;
|
|
61
|
-
}
|
|
62
|
-
/** Причина отбоя словами человека: их шесть, и по каждой видно, что делать дальше. */
|
|
63
|
-
const DENIAL_WORDS = {
|
|
64
|
-
missing: 'такой записи у дерева нет',
|
|
65
|
-
forbidden: 'переход не разрешён порядком',
|
|
66
|
-
'no-fix-note': 'переход в починку без довода `--fix`',
|
|
67
|
-
'extra-fix-note': 'довод `--fix` приехал не с переходом в починку',
|
|
68
|
-
'no-release-version': 'переход в выпуск без довода `--release`',
|
|
69
|
-
'extra-release-version': 'довод `--release` приехал не с переходом в выпуск',
|
|
70
|
-
};
|
|
71
|
-
/** Отбитая строка человеку: род, ключ и причина словами. */
|
|
72
|
-
function deniedLine(kind, key, denial) {
|
|
73
|
-
const why = DENIAL_WORDS[denial] ?? denial;
|
|
74
|
-
return ` ${kind === 'postmortem' ? 'разбор' : 'предложение'} ${key} — ${why}`;
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Отметить записи дерева названным состоянием.
|
|
78
|
-
*
|
|
79
|
-
* Порядок отказов не случаен: сперва то, что видно без сети, — незнакомое состояние, пустой
|
|
80
|
-
* вызов, отсутствующий токен, — и только потом запрос. Холостой ход стоит последним из них:
|
|
81
|
-
* он показывает собранный пакет, а собрать его можно лишь после того, как доводы сошлись.
|
|
82
|
-
*/
|
|
83
|
-
export async function mark(options) {
|
|
84
|
-
if (!CARGO_STATES.includes(options.state)) {
|
|
85
|
-
return refusal(`состояния «${options.state}» не бывает`, `бывают: ${CARGO_STATES.join(', ')}`);
|
|
86
|
-
}
|
|
87
|
-
if (options.items.length === 0) {
|
|
88
|
-
return refusal('отмечать нечего: ни одной записи в доводах', `разбор называется \`${POSTMORTEM_FLAG} <имя файла>\`, предложение — \`${PROPOSAL_FLAG} <признак текста>\``);
|
|
89
|
-
}
|
|
90
|
-
if (!options.token) {
|
|
91
|
-
return refusal('токена дерева нет: отметка осталась неотправленной', 'дерево заводится командой `enroll` — по коду приглашения либо токеном из админки приёма');
|
|
92
|
-
}
|
|
93
|
-
const body = {
|
|
94
|
-
schema: CARGO_SCHEMA_VERSION,
|
|
95
|
-
tree: options.tree,
|
|
96
|
-
items: options.items,
|
|
97
|
-
};
|
|
98
|
-
if (options.dryRun) {
|
|
99
|
-
return {
|
|
100
|
-
code: 0,
|
|
101
|
-
lines: [`уехало бы в ${options.intake}, дерево ${options.tree}:`, ` ${describe(options.items, options.state)}`],
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
const marked = await options.call(options.intake, options.token, body);
|
|
105
|
-
if (!marked.ok || !marked.accepted) {
|
|
106
|
-
return refusal(`${options.intake} ответил ${marked.status || 'молчанием'} — ${marked.said}`);
|
|
107
|
-
}
|
|
108
|
-
const { changed, same, denied } = marked.accepted;
|
|
109
|
-
const counted = `переведено ${changed}, уже стояло ${same}, отбито ${denied.length}`;
|
|
110
|
-
return {
|
|
111
|
-
code: denied.length ? REFUSED : 0,
|
|
112
|
-
lines: [
|
|
113
|
-
`отмечено в ${options.intake}, дерево ${options.tree}: ${counted}`,
|
|
114
|
-
...denied.map((one) => deniedLine(one.kind, one.key, one.denial)),
|
|
115
|
-
],
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
//# sourceMappingURL=cargo-state.js.map
|
package/lib/cargo-state.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cargo-state.js","sourceRoot":"","sources":["../../../projects/agent-kit/src/lib/cargo-state.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Отметка состояния груза: команда, которой исполнитель двигает свои записи в приёме.\n *\n * Разбор доводов и сборка пакета отделены от самого запроса нарочно — тем же приёмом, что и\n * отправка груза: спека подставляет двойник вызова и никуда не стучится, а всё, что можно\n * отбить до сети, отбивается до сети. Незнакомое состояние и вызов без записей — промахи\n * исполнителя, и запрос по ним не уходит вовсе.\n */\nimport { CARGO_SCHEMA_VERSION, CARGO_STATES, ICargoStateAccepted, ICargoStateBody, ICargoStateItem, TCargoStateKind } from './cargo.js';\nimport { IOutcomeOfCommand } from './commands.js';\n\n/** Код возврата у всего, что не легло: отбитая строка кончает команду ненулевым кодом. */\nconst REFUSED: number = 1;\n\n/** Довод, которым называется разбор происшествия. */\nexport const POSTMORTEM_FLAG: string = '--postmortem';\n\n/** Довод, которым называется предложение. */\nexport const PROPOSAL_FLAG: string = '--proposal';\n\n/** Довод текста починки: чем недочёт исправлен. */\nexport const FIX_FLAG: string = '--fix';\n\n/**\n * Довод версии выпуска: в какой версии искать фикс.\n *\n * Назван по выпуску, а не по версии: `--version` у команды строки запуска читается как «покажи\n * свою версию», и заняв его под другое, пакет получил бы две разные вещи под одним словом.\n */\nexport const RELEASE_FLAG: string = '--release';\n\n/** Что приём ответил на правку состояния. Отказ — такой же ответ, как принятое. */\nexport interface IMarked {\n readonly ok: boolean;\n /** Код ответа. Ноль — приём не ответил вовсе: не дозвонились, оборвалось, вышло время. */\n readonly status: number;\n readonly said: string;\n /** Ответ приёма. Пусто у отказа: два числа и отбитые строки он называет только у принятого. */\n readonly accepted: ICargoStateAccepted | null;\n}\n\n/** Чем отметка ходит в приём. Двойник в спеке — того же вида. */\nexport type TMarkCall = (intake: string, token: string, body: ICargoStateBody) => Promise<IMarked>;\n\n/** Приложенные к строке значения: что едет вместе с состоянием. */\nexport interface ICargoStateAttached {\n /** Чем недочёт исправлен. Пустая строка — довода не было. */\n readonly fixNote: string;\n /** В какой версии искать фикс. Пустая строка — довода не было. */\n readonly releaseVersion: string;\n}\n\n/** Всё, что отметке нужно знать: куда, чем представиться и что отмечать. */\nexport interface IMarkOptions {\n readonly intake: string;\n readonly tree: string;\n readonly token: string;\n readonly state: string;\n readonly items: readonly ICargoStateItem[];\n readonly dryRun: boolean;\n readonly call: TMarkCall;\n}\n\n/** Род записи по доводу, которым её назвали. Не наш довод — пусто. */\nfunction kindOfFlag(flag: string): TCargoStateKind | null {\n if (flag === POSTMORTEM_FLAG) {\n return 'postmortem';\n }\n\n return flag === PROPOSAL_FLAG ? 'proposal' : null;\n}\n\n/** Записи, названные доводами строки запуска: род у каждой свой, порядок — как их назвали. */\nexport function itemsOf(\n argv: readonly string[],\n state: string,\n attached: ICargoStateAttached = { fixNote: '', releaseVersion: '' }\n): readonly ICargoStateItem[] {\n const items: ICargoStateItem[] = [];\n\n for (let at: number = 0; at < argv.length; at += 1) {\n const kind: TCargoStateKind | null = kindOfFlag(argv[at]);\n const key: string = argv[at + 1] ?? '';\n\n if (kind && key && !key.startsWith('--')) {\n // Приложенное значение едет полем строки, а не своим вызовом: отметка одна, и все её\n // записи чинились одним разбором либо уехали одним выпуском — второго значения на\n // тот же вызов не задаётся\n items.push({\n kind,\n key,\n state,\n ...(attached.fixNote ? { fixNote: attached.fixNote } : {}),\n ...(attached.releaseVersion ? { releaseVersion: attached.releaseVersion } : {}),\n });\n }\n }\n\n return items;\n}\n\n/** Отказ строками. */\nfunction refusal(...lines: readonly string[]): IOutcomeOfCommand {\n return { code: REFUSED, lines: [...lines] };\n}\n\n/** Пакет одной строкой: её читает человек перед тем, как отправить. */\nfunction describe(items: readonly ICargoStateItem[], state: string): string {\n const postmortems: number = items.filter((one: ICargoStateItem): boolean => one.kind === 'postmortem').length;\n\n return `в «${state}»: разборов ${postmortems}, предложений ${items.length - postmortems}`;\n}\n\n/** Причина отбоя словами человека: их шесть, и по каждой видно, что делать дальше. */\nconst DENIAL_WORDS: Readonly<Record<string, string>> = {\n missing: 'такой записи у дерева нет',\n forbidden: 'переход не разрешён порядком',\n 'no-fix-note': 'переход в починку без довода `--fix`',\n 'extra-fix-note': 'довод `--fix` приехал не с переходом в починку',\n 'no-release-version': 'переход в выпуск без довода `--release`',\n 'extra-release-version': 'довод `--release` приехал не с переходом в выпуск',\n};\n\n/** Отбитая строка человеку: род, ключ и причина словами. */\nfunction deniedLine(kind: string, key: string, denial: string): string {\n const why: string = DENIAL_WORDS[denial] ?? denial;\n\n return ` ${kind === 'postmortem' ? 'разбор' : 'предложение'} ${key} — ${why}`;\n}\n\n/**\n * Отметить записи дерева названным состоянием.\n *\n * Порядок отказов не случаен: сперва то, что видно без сети, — незнакомое состояние, пустой\n * вызов, отсутствующий токен, — и только потом запрос. Холостой ход стоит последним из них:\n * он показывает собранный пакет, а собрать его можно лишь после того, как доводы сошлись.\n */\nexport async function mark(options: IMarkOptions): Promise<IOutcomeOfCommand> {\n if (!CARGO_STATES.includes(options.state)) {\n return refusal(`состояния «${options.state}» не бывает`, `бывают: ${CARGO_STATES.join(', ')}`);\n }\n\n if (options.items.length === 0) {\n return refusal(\n 'отмечать нечего: ни одной записи в доводах',\n `разбор называется \\`${POSTMORTEM_FLAG} <имя файла>\\`, предложение — \\`${PROPOSAL_FLAG} <признак текста>\\``\n );\n }\n\n if (!options.token) {\n return refusal(\n 'токена дерева нет: отметка осталась неотправленной',\n 'дерево заводится командой `enroll` — по коду приглашения либо токеном из админки приёма'\n );\n }\n\n const body: ICargoStateBody = {\n schema: CARGO_SCHEMA_VERSION,\n tree: options.tree,\n items: options.items,\n };\n\n if (options.dryRun) {\n return {\n code: 0,\n lines: [`уехало бы в ${options.intake}, дерево ${options.tree}:`, ` ${describe(options.items, options.state)}`],\n };\n }\n\n const marked: IMarked = await options.call(options.intake, options.token, body);\n\n if (!marked.ok || !marked.accepted) {\n return refusal(`${options.intake} ответил ${marked.status || 'молчанием'} — ${marked.said}`);\n }\n\n const { changed, same, denied }: ICargoStateAccepted = marked.accepted;\n const counted: string = `переведено ${changed}, уже стояло ${same}, отбито ${denied.length}`;\n\n return {\n code: denied.length ? REFUSED : 0,\n lines: [\n `отмечено в ${options.intake}, дерево ${options.tree}: ${counted}`,\n ...denied.map((one: { kind: string; key: string; denial: string }): string => deniedLine(one.kind, one.key, one.denial)),\n ],\n };\n}\n"]}
|
|
Binary file
|