@rt-tools/agent-kit 0.3.0 → 0.4.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/README.md +194 -30
- package/assets/agents/business-analyst.md +74 -0
- package/assets/agents/project-manager.md +70 -0
- package/assets/agents/qa-engineer.md +72 -0
- package/assets/agents/skill-curator.md +110 -0
- package/assets/agents/spec-critic.md +44 -0
- package/assets/agents/spec-writer.md +50 -0
- package/assets/checks/board.github.mjs +286 -0
- package/assets/checks/check-board.github.mjs +188 -0
- package/assets/checks/check-doc-paths.mjs +163 -0
- package/assets/checks/check-dupes.mjs +277 -0
- package/assets/checks/check-lib-layers.mjs +573 -0
- package/assets/checks/check-reuse.mjs +208 -0
- package/assets/checks/check-schema-drift.mjs +186 -0
- package/assets/checks/check-specs.mjs +1007 -0
- package/assets/checks/check-styles.mjs +109 -0
- package/assets/checks/rt-kit-checks.config.mjs +134 -0
- package/assets/checks/task-new.github.mjs +198 -0
- package/assets/commands/skill-curator.md +70 -0
- package/assets/defaults/gate-map.sh +100 -0
- package/assets/defaults/project.sh +179 -0
- package/assets/hooks/browser-device-id.sh +0 -0
- package/assets/hooks/browser-guard-device-id.sh +2 -1
- package/assets/hooks/browser-guard-no-asking.sh +27 -0
- package/assets/hooks/browser-guard-no-listing.sh +2 -1
- package/assets/hooks/browser-guard-no-other-drivers.sh +2 -1
- package/assets/hooks/browser-guard-require-select.sh +2 -1
- package/assets/hooks/commit-msg.sh +1 -1
- package/assets/hooks/constitution-index.sh +5 -4
- package/assets/hooks/dev-server-guard.sh +8 -6
- package/assets/hooks/docs-guard.sh +223 -37
- package/assets/hooks/git-guard-delivery.sh +86 -29
- package/assets/hooks/git-guard-main.sh +1 -0
- package/assets/hooks/git-guard-push-tests.sh +34 -13
- package/assets/hooks/glossary-load.sh +23 -0
- package/assets/hooks/lint-after-edit.sh +155 -30
- package/assets/hooks/qa-dataid-guard.sh +72 -32
- package/assets/hooks/reuse-first-guard.sh +105 -34
- package/assets/hooks/skill-gate-rearm.sh +1 -0
- package/assets/hooks/skill-gate.sh +75 -15
- package/assets/hooks/skill-loaded.sh +1 -0
- package/assets/hooks/sql-guard.sh +606 -56
- package/assets/hooks/task-context-load.sh +100 -0
- package/assets/hooks/task-flow-guard.sh +107 -0
- package/assets/laws/{access.md → application/access.md} +1 -4
- package/assets/laws/{locales.md → application/locales.md} +1 -3
- package/assets/laws/application/money.md +41 -0
- package/assets/laws/application/ownership.md +32 -0
- package/assets/laws/{search-visibility.md → application/search-visibility.md} +1 -1
- package/assets/laws/code-structure.md +7 -6
- package/assets/laws/delivery.md +53 -3
- package/assets/laws/entity-editing.md +49 -55
- package/assets/laws/entity-models.md +4 -14
- package/assets/laws/frontend-application.md +5 -5
- package/assets/laws/lib-imports.md +14 -1
- package/assets/laws/lists.md +33 -0
- package/assets/laws/navigation.md +40 -0
- package/assets/laws/project-documentation.md +17 -8
- package/assets/laws/reuse-first.md +26 -21
- package/assets/laws/shared-code.md +13 -1
- package/assets/laws/verifiability.md +17 -1
- package/assets/laws/work-conduct.md +48 -0
- package/assets/patterns/admin-lists-screen.md +131 -0
- package/assets/patterns/admin-nav-item.md +71 -0
- package/assets/patterns/angular-patterns-state.md +29 -22
- package/assets/patterns/api-layer-pair.md +40 -30
- package/assets/patterns/browser-verification-measure.md +41 -38
- package/assets/patterns/browser-verification-stand.md +106 -42
- package/assets/patterns/component-structure-new.md +33 -32
- package/assets/patterns/dependencies-upgrade.md +65 -0
- package/assets/patterns/doc-style-sweep.md +65 -28
- package/assets/patterns/doc-style-write.md +36 -33
- package/assets/patterns/entity-aside.md +136 -0
- package/assets/patterns/entity-models-new.md +124 -0
- package/assets/patterns/entity-store.md +91 -0
- package/assets/patterns/git-workflow-commit.azure.md +259 -0
- package/assets/patterns/git-workflow-commit.github.md +333 -0
- package/assets/patterns/git-workflow-commit.gitlab.md +283 -0
- package/assets/patterns/git-workflow-merge.md +42 -25
- package/assets/patterns/git-workflow-migration.md +61 -31
- package/assets/patterns/git-workflow-restart.md +20 -20
- package/assets/patterns/lib-layers-move.md +50 -32
- package/assets/patterns/lib-layers-new.md +41 -29
- package/assets/patterns/ownership-scope-resolve.md +69 -0
- package/assets/patterns/permissions-procedure.md +35 -33
- package/assets/patterns/platform-access-di.md +39 -25
- package/assets/patterns/pricing-quote.md +71 -0
- package/assets/patterns/reuse-first-extend.md +22 -22
- package/assets/patterns/seo-page.md +52 -40
- package/assets/patterns/seo-verify.md +48 -29
- package/assets/patterns/shared-code-new.md +37 -31
- package/assets/patterns/spec-driven-domain.md +44 -37
- package/assets/patterns/spec-driven-rule.md +55 -40
- package/assets/patterns/styling-bem-component.md +43 -32
- package/assets/patterns/styling-bem-layout.md +30 -24
- package/assets/patterns/task-flow-close.md +90 -0
- package/assets/patterns/task-flow-resume.md +94 -0
- package/assets/patterns/task-flow-start.md +117 -0
- package/assets/patterns/testing-e2e.md +53 -51
- package/assets/patterns/testing-unit.md +70 -46
- package/assets/patterns/translations-key.md +32 -19
- package/assets/patterns/ts-procedure.md +24 -25
- package/assets/rules/angular-patterns.md +46 -27
- package/assets/rules/api-layer.md +46 -28
- package/assets/rules/browser-verification.md +66 -48
- package/assets/rules/component-structure.md +43 -27
- package/assets/rules/dependencies.md +66 -0
- package/assets/rules/doc-style.md +81 -39
- package/assets/rules/entity-conventions.md +78 -0
- package/assets/rules/entity-models.md +70 -0
- package/assets/rules/git-workflow.azure.md +116 -0
- package/assets/rules/git-workflow.github.md +123 -0
- package/assets/rules/git-workflow.gitlab.md +113 -0
- package/assets/rules/lib-layers.md +56 -30
- package/assets/rules/lists.md +73 -0
- package/assets/rules/navigation.md +78 -0
- package/assets/rules/ownership-scope.md +63 -0
- package/assets/rules/permissions.md +43 -25
- package/assets/rules/platform-access.md +57 -29
- package/assets/rules/pricing.md +64 -0
- package/assets/rules/reuse-first.md +57 -43
- package/assets/rules/seo.md +51 -30
- package/assets/rules/shared-code.md +51 -26
- package/assets/rules/spec-driven.md +96 -50
- package/assets/rules/styling-bem.md +54 -39
- package/assets/rules/task-flow.md +110 -0
- package/assets/rules/testing.md +78 -47
- package/assets/rules/translations.md +48 -31
- package/assets/rules/typescript-conventions.md +57 -27
- package/assets/skills/agent-kit.md +81 -0
- package/assets/skills/write-a-skill.md +108 -0
- package/assets/templates/gate-map.sh +23 -15
- package/assets/templates/implementation.md +14 -8
- package/assets/templates/pattern.md +1 -1
- package/assets/templates/project.sh +32 -19
- package/assets/templates/rule.md +1 -1
- package/assets/variants.json +20 -0
- package/assets/workflows/feature.js +134 -0
- package/assets/workflows/plan.js +150 -0
- package/bin/agent-kit.d.ts.map +1 -1
- package/bin/agent-kit.js +78 -5
- package/bin/agent-kit.js.map +1 -1
- package/bin/prompt.d.ts +5 -0
- package/bin/prompt.d.ts.map +1 -1
- package/bin/prompt.js +19 -7
- package/bin/prompt.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/assets.d.ts +8 -3
- package/lib/assets.d.ts.map +1 -1
- package/lib/assets.js +13 -3
- package/lib/assets.js.map +1 -1
- package/lib/catalog.d.ts +52 -5
- package/lib/catalog.d.ts.map +1 -1
- package/lib/catalog.js +104 -16
- package/lib/catalog.js.map +1 -1
- package/lib/commands.d.ts +22 -1
- package/lib/commands.d.ts.map +1 -1
- package/lib/commands.js +202 -14
- package/lib/commands.js.map +1 -1
- package/lib/companion.d.ts +5 -1
- package/lib/companion.d.ts.map +1 -1
- package/lib/companion.js +29 -2
- package/lib/companion.js.map +1 -1
- package/lib/config.d.ts +26 -9
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js +41 -15
- package/lib/config.js.map +1 -1
- package/lib/freshness.d.ts +14 -0
- package/lib/freshness.d.ts.map +1 -0
- package/lib/freshness.js +116 -0
- package/lib/freshness.js.map +1 -0
- package/lib/hooks-map.d.ts +24 -0
- package/lib/hooks-map.d.ts.map +1 -0
- package/lib/hooks-map.js +72 -0
- package/lib/hooks-map.js.map +1 -0
- package/lib/integrity.d.ts +36 -0
- package/lib/integrity.d.ts.map +1 -0
- package/lib/integrity.js +44 -0
- package/lib/integrity.js.map +1 -0
- package/lib/picker.d.ts +11 -1
- package/lib/picker.d.ts.map +1 -1
- package/lib/picker.js +44 -6
- package/lib/picker.js.map +1 -1
- package/lib/sync.d.ts +26 -0
- package/lib/sync.d.ts.map +1 -1
- package/lib/sync.js +59 -4
- package/lib/sync.js.map +1 -1
- package/lib/variants.d.ts +44 -0
- package/lib/variants.d.ts.map +1 -0
- package/lib/variants.js +82 -0
- package/lib/variants.js.map +1 -0
- package/package.json +1 -1
- package/rt-tools-agent-kit-0.4.0.tgz +0 -0
- package/assets/laws/admin-lists.md +0 -35
- package/assets/laws/admin-navigation.md +0 -38
- package/assets/patterns/git-workflow-commit.md +0 -175
- package/assets/rules/git-workflow.md +0 -106
- package/rt-tools-agent-kit-0.3.0.tgz +0 -0
|
@@ -2,63 +2,82 @@
|
|
|
2
2
|
name: seo-verify
|
|
3
3
|
kind: pattern
|
|
4
4
|
rule: seo
|
|
5
|
-
description: Паттерн правила seo. Брать после любой правки, задевающей
|
|
5
|
+
description: Паттерн правила seo. Брать после любой правки, задевающей разметку публичного сайта, meta или маршруты — готовые команды сборки, поднятия SSR и проверки отданного HTML по локалям, карты сайта и кэшируемости перенаправления. Не брать для самой правки разметки — это паттерн seo-page.
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Проверка разметки на прод-сборке
|
|
9
9
|
|
|
10
|
-
Паттерн правила `seo`. Что при этом должно быть верно — закон
|
|
10
|
+
Паттерн правила `seo`. Что при этом должно быть верно — закон
|
|
11
|
+
`docs/constitution/application/search-visibility.md`.
|
|
11
12
|
|
|
12
13
|
## Когда брать
|
|
13
14
|
|
|
14
|
-
После любой правки, задевающей
|
|
15
|
-
|
|
15
|
+
После любой правки, задевающей разметку сайта, `meta`, маршруты, `server.ts`, `robots.txt`
|
|
16
|
+
или `deploy/nginx.conf`.
|
|
16
17
|
|
|
17
|
-
##
|
|
18
|
+
## Дев-сервер здесь не показатель
|
|
18
19
|
|
|
19
|
-
Теги ставятся при отдаче страницы сервером. В
|
|
20
|
-
|
|
20
|
+
Теги ставятся при отдаче страницы сервером. В дев-режиме этот путь другой, поэтому проверка
|
|
21
|
+
идёт на собранном приложении с поднятым SSR.
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
```bash
|
|
24
|
+
npx nx build site
|
|
25
|
+
PORT={{prodSitePort}} node dist/apps/site/server/server.mjs &
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Порт {{prodSitePort}} — тот же, что берёт стенд; дев-серверы владельца на {{sitePort}} и {{adminPort}} при этом не
|
|
29
|
+
трогаются. Angular SSR отвечает `400` на чужой `Host`, поэтому запросы идут с
|
|
30
|
+
`-H "Host: localhost"`.
|
|
24
31
|
|
|
25
|
-
## Что смотреть в
|
|
32
|
+
## Что смотреть в отданном HTML
|
|
26
33
|
|
|
27
34
|
```bash
|
|
28
|
-
for locale in ""
|
|
29
|
-
printf '%-10s ' "${locale
|
|
30
|
-
curl -s -H "Host: localhost" "http://localhost
|
|
35
|
+
for locale in "" ru/ de/ zh-Hans/ zh-Hant/ ko/ th/ hi/; do
|
|
36
|
+
printf '%-10s ' "${locale:-en}"
|
|
37
|
+
curl -s -H "Host: localhost" "http://localhost:{{prodSitePort}}/${locale}<адрес страницы>" \
|
|
31
38
|
| grep -c -E '<title>|name="description"|property="og:|rel="canonical"|hreflang=|application/ld\+json'
|
|
32
39
|
done
|
|
33
40
|
```
|
|
34
41
|
|
|
35
|
-
В ответе каждой локали должны быть
|
|
36
|
-
|
|
37
|
-
данных.
|
|
42
|
+
В ответе каждой локали должны быть `<title>`, `description`, набор `og:*`, `canonical`,
|
|
43
|
+
полный набор `hreflang` плюс `x-default` и блок `application/ld+json`.
|
|
38
44
|
|
|
39
|
-
Отдельно проверяется, что
|
|
40
|
-
|
|
45
|
+
Отдельно проверяется, что `canonical` ведёт на **свой** язык, а не на локаль по умолчанию:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
curl -s -H "Host: localhost" http://localhost:{{prodSitePort}}/de/<адрес страницы> \
|
|
49
|
+
| grep -o 'rel="canonical" href="[^"]*"'
|
|
50
|
+
```
|
|
41
51
|
|
|
42
52
|
## Карта сайта
|
|
43
53
|
|
|
44
|
-
|
|
45
|
-
|
|
54
|
+
```bash
|
|
55
|
+
curl -s -H "Host: localhost" http://localhost:{{prodSitePort}}/sitemap.xml | head -20
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Карта строится из живых данных, а не из файла. Пустой ответ означает, что не поднялся запрос
|
|
59
|
+
за объектами, — это отказ, а не «объектов нет».
|
|
46
60
|
|
|
47
61
|
## Кэшируемость перенаправления
|
|
48
62
|
|
|
49
|
-
Проверяется только на стенде с настоящим
|
|
50
|
-
|
|
63
|
+
Проверяется только на стенде с настоящим `deploy/nginx.conf`: голый SSR отдаёт заголовки, но
|
|
64
|
+
не показывает, попадёт ли ответ в кэш.
|
|
51
65
|
|
|
52
66
|
```bash
|
|
53
|
-
curl -sI http
|
|
67
|
+
curl -sI http://<стенд>/<прежний-slug> | grep -i -E 'HTTP/|location|cache-control|x-cache'
|
|
54
68
|
```
|
|
55
69
|
|
|
56
|
-
Ответ обязан быть
|
|
70
|
+
Ответ обязан быть `301`, нести `Cache-Control` со сроком и попадать в кэш. Некэшируемое
|
|
71
|
+
перенаправление не вытесняет старую запись, и гость видит прежнюю страницу до суток.
|
|
72
|
+
|
|
73
|
+
## Тексты
|
|
74
|
+
|
|
75
|
+
`title` и `description` берутся из словарей во всех локалях перевода. Непереведённый ключ уезжает
|
|
76
|
+
в выдачу по-английски — полноту словарей держит `npx nx test common-i18n`.
|
|
57
77
|
|
|
58
78
|
## Частые промахи
|
|
59
79
|
|
|
60
|
-
-
|
|
61
|
-
|
|
62
|
-
-
|
|
63
|
-
|
|
64
|
-
- **Заголовки смотрели на голом сервере:** кэш и перенаправления живут в прокси.
|
|
80
|
+
- Проверка в дев-сервере: разметку там ставит другой путь, и отсутствие тега не видно.
|
|
81
|
+
- Проверка одной локали: расходится обычно та, которую не смотрели.
|
|
82
|
+
- Проверка кэша без nginx: заголовки видны, попадание в кэш — нет.
|
|
83
|
+
- Вывод по коду ответа: `200` приходит и со страницы без разметки.
|
|
@@ -2,29 +2,30 @@
|
|
|
2
2
|
name: shared-code-new
|
|
3
3
|
kind: pattern
|
|
4
4
|
rule: shared-code
|
|
5
|
-
description: Паттерн правила shared-code. Брать, когда заводится новое число-настройка, общая функция или общий тип, который должны одинаково понимать
|
|
5
|
+
description: Паттерн правила shared-code. Брать, когда заводится новое число-настройка, общая функция или общий тип, который должны одинаково понимать сайт, админка и бэкенд — куда класть, как объявить, как сверить строку с набором и как убедиться, что копия не осталась на старом месте.
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Новое общее заводится так
|
|
9
9
|
|
|
10
|
-
Паттерн правила `shared-code`. Что при этом должно быть верно — закон
|
|
10
|
+
Паттерн правила `shared-code`. Что при этом должно быть верно — закон
|
|
11
|
+
`docs/constitution/shared-code.md`.
|
|
11
12
|
|
|
12
13
|
## Когда брать
|
|
13
14
|
|
|
14
15
|
- Появилось число-настройка: предел, размер, длительность.
|
|
15
|
-
- Появилась функция без
|
|
16
|
+
- Появилась функция без фреймворка, нужная обеим сторонам.
|
|
16
17
|
- Значение приходит строкой и должно быть сверено с конечным набором.
|
|
17
18
|
|
|
18
19
|
## Куда класть
|
|
19
20
|
|
|
20
|
-
| Что
|
|
21
|
-
|
|
|
22
|
-
| число или функция без
|
|
23
|
-
| готовый тип или набор значений
|
|
24
|
-
| токен
|
|
21
|
+
| Что | Куда |
|
|
22
|
+
| ------------------------------------- | ----------------------------------------------- |
|
|
23
|
+
| число или функция без фреймворка | `libs/common/util`, файл по предмету |
|
|
24
|
+
| готовый тип или набор значений | берётся из `@rt-tools/utils`, не переписывается |
|
|
25
|
+
| токен DI, общий двум фронтовым семьям | `libs/common/platform` |
|
|
25
26
|
|
|
26
|
-
Файл выбирается по
|
|
27
|
-
|
|
27
|
+
Файл выбирается по предмету: `const/list.const.ts`, `functions/list-selection.util.ts`.
|
|
28
|
+
Дальше — строка в барель `libs/common/util/src/index.ts`.
|
|
28
29
|
|
|
29
30
|
## Число объявляется один раз и без довода
|
|
30
31
|
|
|
@@ -33,48 +34,53 @@ export const DEFAULT_PAGE_SIZE: number = 20;
|
|
|
33
34
|
```
|
|
34
35
|
|
|
35
36
|
```typescript
|
|
36
|
-
✗ export function listPageOf(query:
|
|
37
|
-
✓ export function listPageOf(query:
|
|
37
|
+
✗ export function listPageOf(query: ListQuery | undefined, defaultPageSize: number): IListPage
|
|
38
|
+
✓ export function listPageOf(query: ListQuery | undefined): IListPage
|
|
38
39
|
```
|
|
39
40
|
|
|
40
|
-
Пока умолчание передаётся доводом, домен вправе назвать своё число —
|
|
41
|
-
|
|
41
|
+
Пока умолчание передаётся доводом, домен вправе назвать своё число — так у промокодов
|
|
42
|
+
появилось `25` против `20` у остальных списков.
|
|
42
43
|
|
|
43
44
|
## Строка сверяется с набором, а не приводится к типу
|
|
44
45
|
|
|
45
|
-
Приведение принимает любую строку. Сверку делает общая
|
|
46
|
-
|
|
46
|
+
Приведение принимает любую строку. Сверку делает общая пара функций, а что делать с промахом,
|
|
47
|
+
решает вызывающий.
|
|
47
48
|
|
|
48
49
|
```typescript
|
|
49
|
-
const operator:
|
|
50
|
+
const operator: FilterOperatorType | null = listFilterOperatorOf(filter.operatorType);
|
|
50
51
|
if (!operator) {
|
|
51
|
-
throw new
|
|
52
|
+
throw new ConnectError(`filter operator is required: ${filter.propertyName}`, Code.InvalidArgument);
|
|
52
53
|
}
|
|
53
54
|
```
|
|
54
55
|
|
|
55
56
|
```typescript
|
|
56
|
-
const direction:
|
|
57
|
+
const direction: ListSortOrderType = listSortOrderOf(rawDirection) ?? LIST_SORT_ORDER_ENUM.ASC;
|
|
57
58
|
```
|
|
58
59
|
|
|
59
|
-
Сервер отбивает запрос, экран берёт умолчание. Общий
|
|
60
|
+
Сервер отбивает запрос, экран берёт умолчание. Общий маппер здесь не годится: он подал бы
|
|
60
61
|
промах умолчанием, и клиент получил бы отбор, которого не просил.
|
|
61
62
|
|
|
62
|
-
|
|
63
|
-
возвращает
|
|
63
|
+
`typeCast.getAsType` для этого тоже не годится — значение вне набора он пишет в консоль и
|
|
64
|
+
возвращает строкой `'unknown'`.
|
|
64
65
|
|
|
65
66
|
## Проверить, что копия не осталась
|
|
66
67
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
```bash
|
|
69
|
+
npm run check:dupes
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Проверка падает на четырёх признаках: одно имя из двух либ, два перечисления с одинаковым
|
|
73
|
+
набором членов, число-настройка под одним именем в двух либах, перечисление, повторяющее набор
|
|
74
|
+
из `@rt-tools/utils`.
|
|
70
75
|
|
|
71
|
-
Накопленное лежит в
|
|
72
|
-
строка в нём означает, что повтор завели уже после проверки.
|
|
76
|
+
Накопленное лежит в `tools/dupes-allowlist.json` под ключом `debt` и отказом не считается.
|
|
77
|
+
Список только сокращается: новая строка в нём означает, что повтор завели уже после проверки.
|
|
73
78
|
|
|
74
79
|
## Частые промахи
|
|
75
80
|
|
|
76
|
-
- Своё перечисление с теми же членами, что уже есть в
|
|
77
|
-
разошлись.
|
|
81
|
+
- Своё перечисление с теми же членами, что уже есть в `@rt-tools/utils`, — копия, даже если
|
|
82
|
+
имена разошлись.
|
|
78
83
|
- Умолчание, переданное доводом, — домен назовёт своё число, и разъезд будет молчаливым.
|
|
79
|
-
- Ту же логику, написанную заново под другим именем, проверка не
|
|
80
|
-
|
|
84
|
+
- Ту же логику, написанную заново под другим именем, проверка не ловит и ловить не будет —
|
|
85
|
+
такой повтор находит только тот, кто читает правку.
|
|
86
|
+
- Строковая настройка и таблица соответствий не учитываются вовсе — долг `Q-S-2`.
|
|
@@ -2,48 +2,54 @@
|
|
|
2
2
|
name: spec-driven-domain
|
|
3
3
|
kind: pattern
|
|
4
4
|
rule: spec-driven
|
|
5
|
-
description: Паттерн правила spec-driven. Брать при заведении или правке спека домена
|
|
5
|
+
description: Паттерн правила spec-driven. Брать при заведении или правке спека домена в docs/specs — обязательные разделы, форма сценария, привязка правила к коду, порядок работы от спека к коду. Не брать для заведения закона, правила или паттерна — это паттерн spec-driven-rule.
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Спек домена
|
|
9
9
|
|
|
10
10
|
Паттерн правила `spec-driven`. Что при этом должно быть верно — закон
|
|
11
|
-
`
|
|
11
|
+
`docs/constitution/project-documentation.md`.
|
|
12
12
|
|
|
13
13
|
## Когда брать
|
|
14
14
|
|
|
15
|
-
- Заводится новый домен или
|
|
16
|
-
- Правится
|
|
15
|
+
- Заводится новый домен или фича в `proposed/`.
|
|
16
|
+
- Правится `.proto` — спеки задетых доменов едут той же веткой.
|
|
17
17
|
- Замечено расхождение спека с кодом.
|
|
18
18
|
|
|
19
19
|
## Раскладка
|
|
20
20
|
|
|
21
21
|
```
|
|
22
|
-
|
|
22
|
+
docs/specs/<домен>/
|
|
23
23
|
spec.md — как домен работает
|
|
24
24
|
implementation.md — таблица «правило → файл:символ»
|
|
25
25
|
scenarios.md — сценарии SC-<ПРЕФИКС>-<НОМЕР>
|
|
26
26
|
proposed/<фича>/ — только то, чего ещё нет
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
+
Шаблон — `docs/specs/_template/spec.md`, указатель с префиксами — `docs/specs/README.md`.
|
|
30
|
+
|
|
29
31
|
## Обязательные разделы
|
|
30
32
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
`## Зачем` · `## Терминология` с подразделом `### Как это называется в интерфейсе` ·
|
|
34
|
+
`## Правила` · `## Что не входит` · `## Контракт` с подразделом `### Коды отказов` ·
|
|
35
|
+
`## Данные` · `## Экраны и состояния` · `## Сквозные требования` с четырьмя подразделами
|
|
36
|
+
`### Локали`, `### SEO`, `### Мобильная раскладка`, `### Мультиобъектность` · `## Решения` ·
|
|
37
|
+
`## Открытые вопросы` · `## История изменений`.
|
|
38
|
+
|
|
39
|
+
Текст заголовка сверяется дословно. «Не применимо» — законный ответ, отсутствие раздела — нет.
|
|
35
40
|
|
|
36
|
-
Шапка несёт статус, префикс сценариев, зависимости от других доменов, строку
|
|
37
|
-
которые домен применяет, и строку
|
|
41
|
+
Шапка несёт статус, дату ревизии, префикс сценариев, зависимости от других доменов, строку
|
|
42
|
+
`**Законы:**` — законы, которые домен применяет, — и строку `**Процедуры:**` — корни либ, чьи
|
|
43
|
+
процедуры домен обслуживает.
|
|
38
44
|
|
|
39
45
|
```markdown
|
|
40
|
-
**Зависимости:**
|
|
41
|
-
**Законы:** `access`, `locales`, `
|
|
42
|
-
|
|
46
|
+
**Зависимости:** `pricing` (сумма заявки), `availability` (занятость дат)
|
|
47
|
+
**Законы:** `access`, `locales`, `money`, `ownership`
|
|
48
|
+
**Процедуры:** `libs/api/<домен>`
|
|
43
49
|
```
|
|
44
50
|
|
|
45
|
-
Закон, названный где-нибудь в тексте спека, обязан стоять в этой строке: связь сверяется в
|
|
46
|
-
стороны.
|
|
51
|
+
Закон, названный где-нибудь в тексте спека, обязан стоять в этой строке: связь сверяется в
|
|
52
|
+
обе стороны.
|
|
47
53
|
|
|
48
54
|
## Правило и его привязка
|
|
49
55
|
|
|
@@ -56,45 +62,46 @@ description: Паттерн правила spec-driven. Брать при зав
|
|
|
56
62
|
Привязка живёт в `implementation.md` рядом, ключ связи — сам текст правила:
|
|
57
63
|
|
|
58
64
|
```markdown
|
|
59
|
-
| Правило | Где исполняется
|
|
60
|
-
| ------------------------------------- |
|
|
61
|
-
| Применяется одна максимальная скидка. |
|
|
65
|
+
| Правило | Где исполняется |
|
|
66
|
+
| ------------------------------------- | ------------------------------------------------------------------ |
|
|
67
|
+
| Применяется одна максимальная скидка. | `libs/api/<домен>/util/src/lib/quote.calculator.ts:calculateQuote` |
|
|
62
68
|
```
|
|
63
69
|
|
|
64
|
-
Правило, которому места в коде не нашлось, — намерение: ему место в
|
|
65
|
-
формальный якорь.
|
|
70
|
+
Правило, которому места в коде не нашлось, — намерение: ему место в «Открытых вопросах» как
|
|
71
|
+
`Q-N`, а не формальный якорь.
|
|
66
72
|
|
|
67
73
|
## Сценарий
|
|
68
74
|
|
|
69
75
|
```markdown
|
|
70
|
-
### SC
|
|
76
|
+
### SC-BK-19 — подтверждение на занятые даты отбивается
|
|
71
77
|
|
|
72
|
-
Дано у
|
|
78
|
+
Дано у объекта есть подтверждённая бронь на пересекающиеся даты
|
|
73
79
|
Когда владелец подтверждает заявку
|
|
74
|
-
Тогда отказ подаётся владельцу как занятые даты, а не как ошибка
|
|
80
|
+
Тогда отказ подаётся владельцу как занятые даты, а не как ошибка базы
|
|
75
81
|
```
|
|
76
82
|
|
|
77
83
|
Идентификатор ставится в начало заголовка теста, через тире. Сценарий без теста помечается
|
|
78
|
-
|
|
84
|
+
`Не покрыто: <причина>`, сценарий с неполным тестом — `Покрытие: частичное — <чего не
|
|
85
|
+
хватает>`.
|
|
79
86
|
|
|
80
87
|
## Порядок работы
|
|
81
88
|
|
|
82
89
|
1. Задача заводится сценариями: что станет верно, когда работа закончится.
|
|
83
|
-
2. Спек домена правится **до** кода.
|
|
90
|
+
2. Спек домена (или `proposed/<фича>/`) правится **до** кода.
|
|
84
91
|
3. Код пишется под сценарии, тесты называются их идентификаторами.
|
|
85
|
-
4.
|
|
92
|
+
4. `npm run check:specs` — до пуша.
|
|
86
93
|
5. Приёмка идёт по сценариям, а не по пересказу правки.
|
|
87
94
|
|
|
88
95
|
## Частые промахи
|
|
89
96
|
|
|
90
|
-
-
|
|
91
|
-
-
|
|
92
|
-
одна.
|
|
93
|
-
-
|
|
97
|
+
- `tasks.md` в спеке: шаги — артефакт сессии, им место в ветке или в описании PR.
|
|
98
|
+
- Скопированная из контракта таблица полей: источник — `libs/common/proto/proto/<область>/v1/`,
|
|
99
|
+
и компилируется из двух только одна.
|
|
100
|
+
- Колонки и индексы в спеке: они в `prisma/schema.prisma`, а в спеке остаётся правило, которое
|
|
94
101
|
ограничение выражает.
|
|
95
|
-
-
|
|
96
|
-
|
|
97
|
-
-
|
|
98
|
-
-
|
|
99
|
-
нём стоят.
|
|
100
|
-
-
|
|
102
|
+
- Место, где правило исполняется, внутри текста правила: оно меняется при первом рефакторинге,
|
|
103
|
+
и для него заведён `implementation.md`.
|
|
104
|
+
- Пометка «Не покрыто» при существующем тесте — отказ: долг закрыли, а отметку не сняли.
|
|
105
|
+
- Закон, названный в тексте, но забытый в строке `**Законы:**`: по закону тогда не узнать,
|
|
106
|
+
какие домены на нём стоят.
|
|
107
|
+
- Правка `.proto` без спеков задетых доменов: `docs-guard` отбивает такой коммит.
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
name: spec-driven-rule
|
|
3
3
|
kind: pattern
|
|
4
4
|
rule: spec-driven
|
|
5
|
-
description: Паттерн правила spec-driven. Брать при заведении или правке
|
|
5
|
+
description: Паттерн правила spec-driven. Брать при заведении или правке закона в docs/constitution, правила или паттерна в .claude/skills — готовые шапки, набор разделов каждого слоя, таблица привязки, признак того, что правило пора делить. Не брать для спека домена — это паттерн spec-driven-domain.
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Закон, правило и паттерн
|
|
9
9
|
|
|
10
10
|
Паттерн правила `spec-driven`. Что при этом должно быть верно — закон
|
|
11
|
-
`
|
|
11
|
+
`docs/constitution/project-documentation.md`.
|
|
12
12
|
|
|
13
13
|
## Когда брать
|
|
14
14
|
|
|
@@ -18,36 +18,51 @@ description: Паттерн правила spec-driven. Брать при зав
|
|
|
18
18
|
|
|
19
19
|
## Закон
|
|
20
20
|
|
|
21
|
-
`
|
|
22
|
-
Признак закона: попытка положить
|
|
23
|
-
двух.
|
|
21
|
+
`docs/constitution/<закон>.md`. О проекте не знает ничего: ни путей, ни имён файлов, ни
|
|
22
|
+
привязок. Признак закона: попытка положить правило в спек домена заставляет повторить то же
|
|
23
|
+
самое ещё в двух.
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
Слой выбирается по одному вопросу: останется ли статья верной в приложении, где нет ни денег,
|
|
26
|
+
ни локалей перевода, ни второй владеющей сущности. Останется — закон живёт в корне; не
|
|
27
|
+
останется — это закон приложения, и он кладётся в `docs/constitution/application/<закон>.md`. Имя закона одно на
|
|
28
|
+
оба слоя: ни `law:` в шапке правила, ни `**Законы:**` в шапке спека слоя не называют, а два
|
|
29
|
+
закона с одним именем развели бы правило и его закон между собой.
|
|
27
30
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
Разделы: `## Зачем` (без заголовка, вводным абзацем) · `## Статьи` · `## Открытые вопросы`.
|
|
32
|
+
Обязательны только «Статьи» — их и сверяет проверка. «Открытые вопросы» заводятся, когда
|
|
33
|
+
вопрос есть, и стираются вместе с последним закрытым: закрытый вопрос из закона убирается, а
|
|
34
|
+
не превращается в пустой раздел.
|
|
35
|
+
|
|
36
|
+
Ни истории правок, ни доводов о том, почему когда-то выбрали так, в законе нет. Историю
|
|
37
|
+
держит система контроля версий, а довод с отвергнутой альтернативой — свойство работы, а не
|
|
38
|
+
продукта: ему место в «Ловушках» правила под этим законом, где и путям к файлам можно.
|
|
39
|
+
Утверждение, которое нельзя написать как «верно всегда», статьёй не становится вовсе.
|
|
32
40
|
|
|
33
41
|
```markdown
|
|
34
|
-
#
|
|
42
|
+
# Закон о поставке
|
|
35
43
|
|
|
36
44
|
Как правка доезжает до работающего приложения. …
|
|
37
45
|
|
|
46
|
+
**Ревизия:** 2026-08-05
|
|
47
|
+
|
|
38
48
|
## Статьи
|
|
39
49
|
|
|
40
50
|
- **Выкатывается образ того коммита, который выкатывают.** Умолчание «последний» отстаёт от
|
|
41
51
|
главной ветки, и приложение молча возвращается к прежней версии, продолжая отвечать.
|
|
42
52
|
```
|
|
43
53
|
|
|
44
|
-
|
|
54
|
+
Раздел `## Открытые вопросы` заводится, когда вопрос есть, и стирается вместе с последним
|
|
55
|
+
закрытым. Вопрос называется `Q-<буква закона>-<номер>`, говорит, что решение изменит, и несёт
|
|
56
|
+
дату заведения; номер после закрытия не переиспользуется.
|
|
57
|
+
|
|
58
|
+
Поведение кода законом не является: «стор отвечает булевым», «метод называется `save`» — этого
|
|
45
59
|
не видит ни гость, ни владелец. Граница простая: закон описывает то, что видно снаружи
|
|
46
|
-
приложения.
|
|
60
|
+
приложения. Исключение — статья об устройстве кода, которую сверяет машина: якоря читаются
|
|
61
|
+
только под `docs/specs/` и `docs/constitution/`.
|
|
47
62
|
|
|
48
63
|
## Правило
|
|
49
64
|
|
|
50
|
-
|
|
65
|
+
`.claude/skills/<правило>/SKILL.md`. Привязывает закон к этому проекту; на один закон их
|
|
51
66
|
бывает несколько.
|
|
52
67
|
|
|
53
68
|
```markdown
|
|
@@ -55,28 +70,28 @@ description: Паттерн правила spec-driven. Брать при зав
|
|
|
55
70
|
name: git-workflow
|
|
56
71
|
kind: rule
|
|
57
72
|
law: delivery
|
|
58
|
-
description: Правило под
|
|
73
|
+
description: Правило под «Закон о поставке». Брать на … Готовый код — в паттернах …
|
|
59
74
|
---
|
|
60
75
|
```
|
|
61
76
|
|
|
62
|
-
Разделы: `##
|
|
77
|
+
Разделы: `## Как это называется здесь` · `## Где это лежит` · `## Как закон применяется
|
|
78
|
+
здесь` · `## Чего из закона здесь нет` · `## Паттерны` · `## Ловушки`.
|
|
63
79
|
|
|
64
|
-
|
|
65
|
-
|
|
80
|
+
Сверяется только `## Как закон применяется здесь`: каждый его пункт начинается жирной фразой,
|
|
81
|
+
и у каждой жирной фразы есть строка в `implementation.md` рядом.
|
|
66
82
|
|
|
67
83
|
```markdown
|
|
68
|
-
| Статья
|
|
69
|
-
|
|
|
70
|
-
| Образы выкатываются по
|
|
84
|
+
| Статья | Где исполняется |
|
|
85
|
+
| -------------------------------------------------------------- | ----------------------------------- |
|
|
86
|
+
| Образы выкатываются по sha коммита, а не по метке «последний». | `docker-compose.prod.yml:IMAGE_TAG` |
|
|
71
87
|
```
|
|
72
88
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
оно уходит прозой в «Ловушки» или статьёй в закон.
|
|
89
|
+
Утверждение, которому места в коде не нашлось, в этот раздел не ставится: оно уходит прозой в
|
|
90
|
+
«Ловушки» или вопросом `Q-N` в закон.
|
|
76
91
|
|
|
77
92
|
## Паттерн
|
|
78
93
|
|
|
79
|
-
|
|
94
|
+
`.claude/skills/<правило>-<что>/SKILL.md`. Минимум один на правило.
|
|
80
95
|
|
|
81
96
|
```markdown
|
|
82
97
|
---
|
|
@@ -87,26 +102,26 @@ description: Паттерн правила git-workflow. Брать … Не б
|
|
|
87
102
|
---
|
|
88
103
|
```
|
|
89
104
|
|
|
90
|
-
Разделы: `## Когда брать` · готовый код · `## Частые промахи`.
|
|
91
|
-
сверять готовый код с ним самим нечем.
|
|
105
|
+
Разделы: `## Когда брать` · готовый код · `## Частые промахи`. Привязки у паттерна нет:
|
|
106
|
+
проверка его не сверяет, потому что сверять готовый код с ним самим нечем.
|
|
92
107
|
|
|
93
108
|
## Порядок
|
|
94
109
|
|
|
95
110
|
1. Статья пишется в закон — без путей и имён файлов.
|
|
96
|
-
2. Правило объявляет закон в шапке и называет
|
|
97
|
-
3.
|
|
98
|
-
|
|
111
|
+
2. Правило объявляет закон в шапке и называет то же самое в терминах этого дерева.
|
|
112
|
+
3. Каждое утверждение правила получает строку в `implementation.md`; якорь проверяется
|
|
113
|
+
открытием файла, а не памятью.
|
|
99
114
|
4. Готовый код уезжает в паттерн, а правило на него ссылается.
|
|
100
|
-
5.
|
|
115
|
+
5. `npm run check:specs` — до пуша.
|
|
101
116
|
|
|
102
117
|
## Частые промахи
|
|
103
118
|
|
|
104
|
-
- Закон назвал файл
|
|
105
|
-
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
-
|
|
110
|
-
перестанет её находить.
|
|
111
|
-
- В
|
|
119
|
+
- Закон назвал файл проекта — проверка отбивает. Путям место в правиле.
|
|
120
|
+
- Спутник с привязкой лежит рядом с законом: он привязывает закон к этому проекту, а зелёная
|
|
121
|
+
проверка это утвердит, потому что структура совпадёт с тем, чего проверка сама и ждёт.
|
|
122
|
+
- Якорь ведёт в мёртвый символ: объявлен и больше нигде не встречается. Так пять правил про
|
|
123
|
+
правку сущности оказались привязаны к механике, которую не зовёт ни один экран.
|
|
124
|
+
- Утверждение переформулировали, а строку в привязке не тронули: связь идёт по тексту, и
|
|
125
|
+
проверка перестанет её находить.
|
|
126
|
+
- В `description` не сказано, когда паттерн **не** брать, — соседний паттерн того же правила
|
|
112
127
|
становится неотличимым.
|