@rt-tools/agent-kit 0.3.0 → 0.5.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 +329 -0
- package/assets/checks/check-board.github.mjs +181 -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 +1086 -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 +106 -0
- package/assets/defaults/project.sh +204 -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 +171 -31
- 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/grill-gate.sh +96 -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 +118 -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 +27 -8
- package/assets/laws/reuse-first.md +26 -21
- package/assets/laws/shared-code.md +13 -1
- package/assets/laws/verifiability.md +30 -1
- package/assets/laws/work-conduct.md +59 -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 +337 -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 +60 -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 +154 -0
- package/assets/patterns/task-flow-resume.md +94 -0
- package/assets/patterns/task-flow-start.md +129 -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 +50 -27
- package/assets/rules/api-layer.md +46 -28
- package/assets/rules/browser-verification.md +67 -48
- package/assets/rules/component-structure.md +43 -27
- package/assets/rules/dependencies.md +66 -0
- package/assets/rules/doc-style.md +95 -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 +107 -51
- package/assets/rules/styling-bem.md +54 -39
- package/assets/rules/task-flow.md +150 -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 +85 -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 +2 -2
- 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 +27 -0
- package/lib/hooks-map.d.ts.map +1 -0
- package/lib/hooks-map.js +77 -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.5.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,13 +2,13 @@
|
|
|
2
2
|
name: component-structure-new
|
|
3
3
|
kind: pattern
|
|
4
4
|
rule: component-structure
|
|
5
|
-
description: Паттерн правила component-structure. Брать при заведении или правке
|
|
5
|
+
description: Паттерн правила component-structure. Брать при заведении или правке *.component.ts — готовый декоратор с порядком свойств, группировка импортов, раскладка полей класса, договорённости шаблона и qa-dataid. Не брать для состояния и потоков — это паттерн angular-patterns-state.
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Файл компонента
|
|
9
9
|
|
|
10
10
|
Паттерн правила `component-structure`. Что при этом должно быть верно — закон
|
|
11
|
-
`
|
|
11
|
+
`docs/constitution/frontend-application.md`.
|
|
12
12
|
|
|
13
13
|
## Когда брать
|
|
14
14
|
|
|
@@ -25,14 +25,14 @@ description: Паттерн правила component-structure. Брать пр
|
|
|
25
25
|
changeDetection: ChangeDetectionStrategy.OnPush, // 4. стратегия перерисовки
|
|
26
26
|
imports: [
|
|
27
27
|
// 5. импорты, группами
|
|
28
|
-
//
|
|
28
|
+
// angular
|
|
29
29
|
FormsModule,
|
|
30
30
|
|
|
31
|
-
//
|
|
31
|
+
// rt-tools
|
|
32
32
|
BlockDirective,
|
|
33
33
|
ElemDirective,
|
|
34
34
|
|
|
35
|
-
//
|
|
35
|
+
// components
|
|
36
36
|
SomeChildComponent,
|
|
37
37
|
],
|
|
38
38
|
providers: [], // 6. провайдеры
|
|
@@ -44,55 +44,56 @@ export class ComponentNameComponent {
|
|
|
44
44
|
public readonly data: InputSignal<Item[]> = input.required<Item[]>();
|
|
45
45
|
public readonly save: OutputEmitterRef<void> = output<void>();
|
|
46
46
|
|
|
47
|
+
protected readonly myButton: Signal<ElementRef | undefined> = viewChild<ElementRef>('button');
|
|
47
48
|
protected readonly items: WritableSignal<Item[]> = signal<Item[]>([]);
|
|
48
49
|
protected readonly itemCount: Signal<number> = computed((): number => this.items().length);
|
|
49
50
|
}
|
|
50
51
|
```
|
|
51
52
|
|
|
52
|
-
Группирующие комментарии в
|
|
53
|
-
|
|
53
|
+
Группирующие комментарии в `imports` обязательны: `// angular`, `// rt-tools`,
|
|
54
|
+
`// components`, `// directives`, `// pipes`.
|
|
54
55
|
|
|
55
56
|
## Шаблон
|
|
56
57
|
|
|
57
|
-
- Самозакрывающиеся теги у компонентов без
|
|
58
|
-
- Лишних обёрток нет — корнем работает
|
|
59
|
-
- Сложный шаблон объявляет блок
|
|
60
|
-
- Один компонент в обеих ветках
|
|
58
|
+
- Самозакрывающиеся теги у компонентов без содержимого: `<<префикс>-gallery />`.
|
|
59
|
+
- Лишних обёрток нет — корнем работает `:host`, класс блока приходит с `host: { class: … }`.
|
|
60
|
+
- Сложный шаблон объявляет блок `<ng-container rtBlock="component-name">` в корне.
|
|
61
|
+
- Один компонент в обеих ветках `@if` — это условная привязка:
|
|
61
62
|
|
|
62
63
|
```html
|
|
63
64
|
<!-- ✗ -->
|
|
64
|
-
@if (isRangeMode()) {
|
|
65
|
-
<calendar [rangeMode]="true" />
|
|
66
|
-
} @else {
|
|
67
|
-
<calendar [rangeMode]="false" />
|
|
68
|
-
}
|
|
65
|
+
@if (isRangeMode()) { <<префикс>-calendar [rangeMode]="true" /> } @else { <<префикс>-calendar [rangeMode]="false" /> }
|
|
69
66
|
|
|
70
67
|
<!-- ✓ -->
|
|
71
|
-
|
|
68
|
+
<<префикс>-calendar [rangeMode]="isRangeMode()" />
|
|
72
69
|
```
|
|
73
70
|
|
|
74
|
-
- Прокрутка по документу —
|
|
75
|
-
|
|
71
|
+
- Прокрутка по документу — через роутер, а не `href="#id"`:
|
|
72
|
+
|
|
73
|
+
```html
|
|
74
|
+
<a fragment="booking" [routerLink]="[]">…</a>
|
|
75
|
+
```
|
|
76
76
|
|
|
77
|
-
##
|
|
77
|
+
## `qa-dataid` — на каждый интерактивный элемент
|
|
78
78
|
|
|
79
79
|
```html
|
|
80
|
-
<button qa-dataid="calendar-retry-prices" type="button" (click)="retryPrices.emit()">Повторить</button>
|
|
80
|
+
<button vmButton qa-dataid="calendar-retry-prices" type="button" (click)="retryPrices.emit()">Повторить</button>
|
|
81
81
|
<div rtElem="grid" qa-dataid="admin-calendar-grid"></div>
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
-
- Значение —
|
|
84
|
+
- Значение — kebab-case по смыслу элемента, без имени компонента-обёртки: `calendar-day`,
|
|
85
|
+
`booking-submit`.
|
|
85
86
|
- Уникальность — в пределах экрана; повторяющиеся элементы списка носят один якорь и
|
|
86
|
-
различаются
|
|
87
|
-
- Декоративный элемент помечается
|
|
87
|
+
различаются через `data-*` (`[attr.data-iso]`, `[attr.data-state]`).
|
|
88
|
+
- Декоративный элемент помечается `qa-skip` на самом теге.
|
|
88
89
|
|
|
89
90
|
## Частые промахи
|
|
90
91
|
|
|
91
|
-
-
|
|
92
|
-
-
|
|
93
|
-
-
|
|
94
|
-
|
|
95
|
-
-
|
|
96
|
-
раскладка уезжает на
|
|
97
|
-
-
|
|
98
|
-
-
|
|
92
|
+
- `selector: 'app-component'` вместо `<префикс>-component`.
|
|
93
|
+
- `styleUrls: ['./component.scss']` вместо `styleUrl` — множественное число здесь не то.
|
|
94
|
+
- Вызов метода в биндинге: `{{ getTotal() }}` отбивается линтером. Замена — `computed()`, а
|
|
95
|
+
там, где значение приходит из контекста шаблона, — чистый пайп.
|
|
96
|
+
- Обёртка, которая существует только чтобы быть flex- или grid-контейнером вокруг всех детей:
|
|
97
|
+
её раскладка уезжает на `:host`.
|
|
98
|
+
- Глубокий относительный импорт между либами вместо `@<область>/<семья>/<домен>/<слой>`.
|
|
99
|
+
- Своя разметка вместо готового компонента кита — правило `reuse-first`.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dependencies-upgrade
|
|
3
|
+
kind: pattern
|
|
4
|
+
rule: dependencies
|
|
5
|
+
description: Паттерн правила dependencies. Брать при подъёме версий пакетов — выбор верхней границы по peer-диапазонам, порядок проверок, граница переформатирования после обновления форматтера, разбор новых правил линтера. Не брать для ветки, коммита и PR — это паттерн git-workflow-commit.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Подъём версий
|
|
9
|
+
|
|
10
|
+
Паттерн правила `dependencies`. Что при этом должно быть верно — закон
|
|
11
|
+
`docs/constitution/delivery.md`.
|
|
12
|
+
|
|
13
|
+
## Когда брать
|
|
14
|
+
|
|
15
|
+
- Поднимается версия любого пакета.
|
|
16
|
+
- Пришло предупреждение об уязвимости в транзитивной зависимости.
|
|
17
|
+
- После установки посыпались замечания линтера или переформатировалось дерево.
|
|
18
|
+
|
|
19
|
+
## Верхнюю границу задают peer-диапазоны
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm view @angular/compiler-cli@22.1.0 peerDependencies
|
|
23
|
+
npm view typescript versions --json | tail -5
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Пакет поднимают до последней версии, которая ещё попадает в peer-диапазон каждого, кто от него
|
|
27
|
+
зависит, а не до последней в реестре. Проверять приходится по одному пакету: `autoInstallPeers:
|
|
28
|
+
true` молча доставляет недостающее, и конфликт peer-диапазонов установку не останавливает.
|
|
29
|
+
|
|
30
|
+
## Порядок
|
|
31
|
+
|
|
32
|
+
1. `package.json` — точные номера, ни одного `^` и `~`.
|
|
33
|
+
2. `pnpm install`; снимок едет тем же коммитом.
|
|
34
|
+
3. `npx nx run-many -t build -p site admin api` — сборка **до** линтеров: о несовместимости
|
|
35
|
+
типов она говорит одной строкой, а линтер на том же дереве даёт сотню замечаний, и
|
|
36
|
+
настоящая причина в них теряется.
|
|
37
|
+
4. `npm run lint` и `npm run stylelint`.
|
|
38
|
+
5. Тесты — правило `testing`. После смены версии Playwright сначала
|
|
39
|
+
`npx playwright install chromium`.
|
|
40
|
+
6. Обход экранов в браузере — правило `browser-verification`: если пакет рисует вёрстку, смену
|
|
41
|
+
его версии тесты не покрывают.
|
|
42
|
+
|
|
43
|
+
## Переформатирование
|
|
44
|
+
|
|
45
|
+
Обновлённый форматтер меняет все файлы дерева. Что из этого оставлять, решает не размер дифа,
|
|
46
|
+
а то, чьё форматирование проверяет линтер: `.ts` и `.html` — `eslint.config.mjs`, `.scss` —
|
|
47
|
+
`stylelint.config.js`. Остальное переформатируется потом, вместе с правкой, которая эти файлы
|
|
48
|
+
и так трогает: полный прогон изменил 883 файла, из которых проверяются 85, и осмысленные
|
|
49
|
+
правки в такой куче не разглядеть.
|
|
50
|
+
|
|
51
|
+
## Новые правила линтера
|
|
52
|
+
|
|
53
|
+
Правило, которое запрещает приём, принятый в этом дереве, выключают один раз в конфиге и
|
|
54
|
+
пишут рядом причину. Правило, которое право по существу, обходят точечным
|
|
55
|
+
`eslint-disable-next-line` — тоже с причиной. Смешивать нельзя: выключенное в конфиге без
|
|
56
|
+
причины через месяц выглядит забытым, а шестьдесят пять точечных обходов одного правила —
|
|
57
|
+
списком того, что надо было выключить один раз.
|
|
58
|
+
|
|
59
|
+
## Частые промахи
|
|
60
|
+
|
|
61
|
+
- `pnpm install` не двигает пакет, если он назван в `overrides`: строка из списка держит
|
|
62
|
+
прежнюю версию, а установка проходит без ошибок.
|
|
63
|
+
- Линтеры до сборки — лишний круг: разбираешь замечания, которых после сборки не будет.
|
|
64
|
+
- Обновление, попавшее в ветку с другой задачей, откатится только вместе с ней: у обновления
|
|
65
|
+
зависимостей своя задача и своя ветка.
|
|
@@ -8,8 +8,8 @@ description: Паттерн правила doc-style. Брать, когда д
|
|
|
8
8
|
# Разбор документа, накопившего список работ
|
|
9
9
|
|
|
10
10
|
Паттерн правила `doc-style`. Что при этом должно быть верно — закон
|
|
11
|
-
`
|
|
12
|
-
месте.
|
|
11
|
+
`docs/constitution/project-documentation.md`, статья о том, что предстоящая работа
|
|
12
|
+
перечислена в одном месте.
|
|
13
13
|
|
|
14
14
|
## Когда брать
|
|
15
15
|
|
|
@@ -31,63 +31,99 @@ description: Паттерн правила doc-style. Брать, когда д
|
|
|
31
31
|
| описание сделанного | удаляется без переноса: о нём говорят закрытые задачи и история |
|
|
32
32
|
| утверждение, разошедшееся с деревом | удаляется как протухшее, а не переносится в задачу |
|
|
33
33
|
|
|
34
|
-
Спрашивать владельца об этом наборе не нужно — он записан здесь. Спрашивать стоит одно:
|
|
35
|
-
самого файла, когда в нём не осталось ничего.
|
|
34
|
+
Спрашивать владельца об этом наборе не нужно — он записан здесь. Спрашивать стоит одно:
|
|
35
|
+
судьбу самого файла, когда в нём не осталось ничего.
|
|
36
36
|
|
|
37
37
|
## Обход идёт по утверждениям, а не по пунктам
|
|
38
38
|
|
|
39
|
-
Работа лежит и в
|
|
40
|
-
|
|
39
|
+
Работа лежит и в прозе. Раздел «Экран заявок» перечислял недостающие якоря сплошным текстом,
|
|
40
|
+
без единого маркера, и обход по `- ` его не увидел бы.
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
```bash
|
|
43
|
+
# сколько чего в файле: пункты, абзацы, разделы
|
|
44
|
+
grep -c '^- ' docs/BACKLOG.md
|
|
45
|
+
grep -c '^## ' docs/BACKLOG.md
|
|
46
|
+
```
|
|
43
47
|
|
|
44
|
-
|
|
45
|
-
|
|
48
|
+
Абзац судится тем же признаком, что и пункт.
|
|
49
|
+
|
|
50
|
+
## Номер задачи стоит в трёх местах
|
|
51
|
+
|
|
52
|
+
Прежде чем считать «пункты без задачи», надо знать все формы записи. В этом дереве их три:
|
|
53
|
+
|
|
54
|
+
```markdown
|
|
55
|
+
## Раздел — #149 ← в заголовке
|
|
56
|
+
|
|
57
|
+
**Тикеты:** #163, #164 ← отдельной строкой у раздела или подраздела
|
|
58
|
+
|
|
59
|
+
- Пункт про дефект. #101 ← в конце пункта
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Разбор, знающий одну форму, ошибается молча: «51 пункт без задачи» оказался шестью. **Число,
|
|
46
63
|
полученное разбором текста, сверяется на выборке руками до того, как его называют.**
|
|
47
64
|
|
|
48
65
|
## Сверка с очередью работ
|
|
49
66
|
|
|
50
67
|
У пункта есть задача — это ещё не значит, что задача несёт его содержание. Перед удалением
|
|
51
|
-
меряется покрытие: сколько значимых слов пункта встречается в теле его задачи.
|
|
52
|
-
|
|
68
|
+
меряется покрытие: сколько значимых слов пункта встречается в теле его задачи.
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
/opt/homebrew/bin/gh issue list --state all --limit 400 --json number,title,body,state > /tmp/issues.json
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Пункт, покрытый телом наполовину и меньше, читается глазами и разводится на три исхода:
|
|
53
75
|
|
|
54
76
|
- живое уточнение, которого в задаче нет, — дописать в тело;
|
|
55
77
|
- другой дефект — завести своей задачей;
|
|
56
|
-
- протухшее — удалить, **не** перенося. Иначе разбор занесёт в задачу
|
|
78
|
+
- протухшее — удалить, **не** перенося. Иначе разбор занесёт в задачу ложь: «гард не проверяет
|
|
79
|
+
каталог кита» переносить было некуда, каталога уже не существовало.
|
|
57
80
|
|
|
58
81
|
**Наследование номера от заголовка — предположение, а не факт.** Пункт под заголовком с
|
|
59
|
-
|
|
82
|
+
четырьмя номерами не принадлежит ни одному из них: привязка проверяется чтением.
|
|
60
83
|
|
|
61
84
|
## Сделанность читается по дереву
|
|
62
85
|
|
|
63
|
-
Утверждение о том, что задача не сделана, стареет так же, как любое другое.
|
|
64
|
-
|
|
86
|
+
Утверждение о том, что задача не сделана, стареет так же, как любое другое. Дважды за один
|
|
87
|
+
разбор устаревшее было названо действующим: маркер непросмотренного уже вёз кит, а половина
|
|
88
|
+
задачи про гейт скилов была сделана и покрыта сценариями.
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
# проверять то, о чём собираешься сказать «не сделано»
|
|
92
|
+
grep -rn '<символ>' libs apps .claude/hooks
|
|
93
|
+
grep -n '<имя>' node_modules/<пакет>/types/*.d.ts
|
|
94
|
+
```
|
|
65
95
|
|
|
66
96
|
## Доводы за отсрочку — это «чего это стоит»
|
|
67
97
|
|
|
68
|
-
Раздел «что стоит отложить» переезжает не в архив, а **в тела тех задач, которых он
|
|
69
|
-
там он и есть оценка цены. В файле он остаётся, только если отсрочка — решение
|
|
70
|
-
предложение разбора. Признак — записанный ответ владельца с
|
|
98
|
+
Раздел «что стоит отложить» переезжает не в архив, а **в тела тех задач, которых он
|
|
99
|
+
касается**: там он и есть оценка цены. В файле он остаётся, только если отсрочка — решение
|
|
100
|
+
владельца, а не предложение разбора. Признак — записанный ответ владельца с датой; нет
|
|
101
|
+
его — значит, предложение.
|
|
71
102
|
|
|
72
103
|
## Ссылки на снятые разделы
|
|
73
104
|
|
|
74
|
-
Задача, чьё тело
|
|
75
|
-
этого не видит: она читает файлы репозитория, а не тела задач.
|
|
105
|
+
Задача, чьё тело говорит `**Источник:** <документ>, раздел «…»`, после разбора ведёт в
|
|
106
|
+
пустоту, и проверка путей этого не видит: она читает файлы репозитория, а не тела задач.
|
|
107
|
+
Строка снимается тем же заходом.
|
|
76
108
|
|
|
77
109
|
## Судьба файла
|
|
78
110
|
|
|
79
|
-
- Осталось незадачное — файл живёт, и его
|
|
80
|
-
- Не осталось ничего, а документ описывал состоявшуюся работу — уезжает в
|
|
111
|
+
- Осталось незадачное — файл живёт, и его преамбула объявляет новый признак отбора.
|
|
112
|
+
- Не осталось ничего, а документ описывал состоявшуюся работу — уезжает в `docs/archive/`.
|
|
81
113
|
- Не осталось ничего, и это был список работ — удаляется.
|
|
82
114
|
|
|
83
|
-
Разбор целиком — одна задача и одна ветка: делится то, что придётся откатывать порознь, а
|
|
84
|
-
откат общий. Правка кода, найденная по дороге, в эту ветку не идёт — иначе откат разбора
|
|
85
|
-
починку.
|
|
115
|
+
Разбор целиком — одна задача и одна ветка: делится то, что придётся откатывать порознь, а
|
|
116
|
+
здесь откат общий. Правка кода, найденная по дороге, в эту ветку не идёт — иначе откат разбора
|
|
117
|
+
унесёт починку.
|
|
86
118
|
|
|
87
119
|
## Что чинится в дереве следом
|
|
88
120
|
|
|
89
|
-
Документ — не единственное место, обещающее, что работа живёт в нём. Снятое имя вычищается
|
|
90
|
-
|
|
121
|
+
Документ — не единственное место, обещающее, что работа живёт в нём. Снятое имя вычищается
|
|
122
|
+
одним грепом, включая описания агентов, скилы, README и комментарии в коде:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
grep -rn 'BACKLOG' --exclude-dir=node_modules --exclude-dir=.git --exclude-dir=archive .
|
|
126
|
+
```
|
|
91
127
|
|
|
92
128
|
## Частые промахи
|
|
93
129
|
|
|
@@ -96,5 +132,6 @@ description: Паттерн правила doc-style. Брать, когда д
|
|
|
96
132
|
- Число пунктов названо владельцу до сверки на выборке.
|
|
97
133
|
- Протухшее утверждение перенесено в задачу и стало действующим указанием.
|
|
98
134
|
- Доводы за отсрочку оставлены в документе: он снова становится вторым списком работ.
|
|
99
|
-
- Разбор поделён на несколько задач «по объёму» — признак деления не объём, а раздельный
|
|
135
|
+
- Разбор поделён на несколько задач «по объёму» — признак деления не объём, а раздельный
|
|
136
|
+
откат.
|
|
100
137
|
- Архив тронут: он описывает состояние на момент написания и под новые термины не правится.
|
|
@@ -8,52 +8,53 @@ description: Паттерн правила doc-style. Брать при напи
|
|
|
8
8
|
# Как формулировать
|
|
9
9
|
|
|
10
10
|
Паттерн правила `doc-style`. Что при этом должно быть верно — закон
|
|
11
|
-
`
|
|
11
|
+
`docs/constitution/project-documentation.md`.
|
|
12
12
|
|
|
13
13
|
## Когда брать
|
|
14
14
|
|
|
15
15
|
- Пишется правило, статья закона, пункт спека или README.
|
|
16
16
|
- Пишется комментарий в коде, тело коммита, описание PR.
|
|
17
17
|
|
|
18
|
-
##
|
|
18
|
+
## Правило — одна фраза
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
Само правило укладывается в одно предложение. Следом — не больше двух предложений о том, что
|
|
21
21
|
сломается иначе, и только если из самой фразы это не видно. Обоснование, у которого была
|
|
22
|
-
альтернатива, идёт в «Ловушки» правила, а не в закон: разросшийся
|
|
23
|
-
закон говорит, что верно, — не почему когда-то выбрали так.
|
|
22
|
+
альтернатива, идёт в «Ловушки» правила, а не в сам закон: разросшийся буллет читают по
|
|
23
|
+
диагонали, а закон говорит, что верно, — не почему когда-то выбрали так.
|
|
24
24
|
|
|
25
25
|
```
|
|
26
|
-
✗ **Взрослых в
|
|
27
|
-
границу держит
|
|
28
|
-
Верхнюю ограничением
|
|
29
|
-
владельцем.
|
|
26
|
+
✗ **Взрослых в брони хотя бы один — на любом пути записи, без исключений.** Нижнюю
|
|
27
|
+
границу держит база: путей записи три, и проверка в одном из них закрывает не все.
|
|
28
|
+
Верхнюю (вместимость объекта) ограничением базы не выразить — она лежит в строке
|
|
29
|
+
объекта и меняется владельцем.
|
|
30
30
|
|
|
31
|
-
✓ **Взрослых в
|
|
32
|
-
✓ **Взрослые и дети не превышают
|
|
31
|
+
✓ **Взрослых в брони хотя бы один.** Исключений нет: заезда без взрослых не бывает.
|
|
32
|
+
✓ **Взрослые и дети не превышают вместимость объекта.**
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
## Что верно, а не где это держится
|
|
36
36
|
|
|
37
|
-
«Держит
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
«Держит база, а не сервис», «проверяется в транзакции», «умолчание колонки», «на трёх путях
|
|
38
|
+
записи из четырёх», имена функций и колонок внутри фразы — это устройство кода. Читателю нужно
|
|
39
|
+
знать, **что** верно.
|
|
40
40
|
|
|
41
|
-
Место исполнения меняется при первом же
|
|
42
|
-
молча. Для него заведён отдельный файл — `implementation.md`
|
|
41
|
+
Место исполнения меняется при первом же рефакторинге, и документ, который его называет,
|
|
42
|
+
устаревает молча. Для него заведён отдельный файл — `implementation.md` рядом.
|
|
43
43
|
|
|
44
|
-
Исключение — «Ловушки» правила: там устройство кода называется прямо, потому что ловушка и
|
|
45
|
-
место, где на него наступают.
|
|
44
|
+
Исключение — «Ловушки» правила: там устройство кода называется прямо, потому что ловушка и
|
|
45
|
+
есть место, где на него наступают.
|
|
46
46
|
|
|
47
47
|
## Без утверждений о будущем
|
|
48
48
|
|
|
49
|
-
«Не планируется», «не будет», «отдельная
|
|
49
|
+
«Не планируется», «не будет», «отдельная фича по запросу» — это намерение владельца, а не
|
|
50
50
|
свойство системы. Что не сделано — да, почему не сделано — да, что не будет сделано никогда —
|
|
51
|
-
нет.
|
|
51
|
+
нет. Вместо приговора — открытый вопрос `Q-N` с тем, что решение изменит.
|
|
52
52
|
|
|
53
|
-
Ошибка беззвучная: сверять утверждение о будущем не с чем, оно проходит любую проверку.
|
|
53
|
+
Ошибка беззвучная: сверять утверждение о будущем не с чем, оно проходит любую проверку. Так в
|
|
54
|
+
первый живой спек попало «онлайн-оплаты нет и не планируется», хотя оплата в планах.
|
|
54
55
|
|
|
55
|
-
Отсюда же: того, чего нет в
|
|
56
|
-
звучит убедительнее исходника — он короче и категоричнее.
|
|
56
|
+
Отсюда же: того, чего нет в `docs/PRD.md`, документ о продукте не утверждает. Домысел при
|
|
57
|
+
пересказе звучит убедительнее исходника — он короче и категоричнее.
|
|
57
58
|
|
|
58
59
|
## Простыми словами
|
|
59
60
|
|
|
@@ -61,9 +62,10 @@ description: Паттерн правила doc-style. Брать при напи
|
|
|
61
62
|
|
|
62
63
|
```
|
|
63
64
|
✗ запись о прошлом не должна упираться в правило, появившееся позже
|
|
65
|
+
✗ свою запись владельца стирать по молчанию площадки нельзя
|
|
64
66
|
✗ пустой список без текста и отказ без кнопки выглядят одинаково — как сломанная страница
|
|
65
67
|
|
|
66
|
-
✓
|
|
68
|
+
✓ бронь, которую владелец внёс сам, пропажа события из фида не снимает
|
|
67
69
|
✓ у пустого списка должен быть текст, у отказа — кнопка повтора
|
|
68
70
|
```
|
|
69
71
|
|
|
@@ -71,23 +73,24 @@ description: Паттерн правила doc-style. Брать при напи
|
|
|
71
73
|
|
|
72
74
|
## Факт проверяется, а не вспоминается
|
|
73
75
|
|
|
74
|
-
Перед тем как написать, что код делает
|
|
76
|
+
Перед тем как написать, что код делает X, — открыть код и посмотреть. Пересказ по памяти
|
|
75
77
|
выглядит так же уверенно, как проверенное утверждение, и отличить их потом нечем.
|
|
76
78
|
|
|
77
|
-
Особенно это касается отказов:
|
|
78
|
-
|
|
79
|
+
Особенно это касается отказов: «вернётся `value out of range`» продержалось в двух документах,
|
|
80
|
+
хотя такой отказ недостижим — в контракте и в колонке одна ширина.
|
|
79
81
|
|
|
80
82
|
## Не пересказывать то, у чего есть источник
|
|
81
83
|
|
|
82
|
-
- типы и поля контракта —
|
|
83
|
-
- колонки и индексы —
|
|
84
|
-
- числа, которые правит
|
|
84
|
+
- типы и поля контракта — `libs/common/proto/proto/<область>/v1/`, ссылкой;
|
|
85
|
+
- колонки и индексы — `prisma/schema.prisma`;
|
|
86
|
+
- числа, которые правит владелец (базовая цена, min-nights, вместимость) — только как они
|
|
87
|
+
применяются;
|
|
85
88
|
- слои и имена классов — правило `lib-layers` и сам код.
|
|
86
89
|
|
|
87
90
|
## Комментарии в коде
|
|
88
91
|
|
|
89
|
-
Те же правила. Комментарий отвечает на вопрос «почему так, а не иначе» — если ответ
|
|
90
|
-
Что делает строка, видно из строки.
|
|
92
|
+
Те же правила. Комментарий отвечает на вопрос «почему так, а не иначе» — если ответ
|
|
93
|
+
неочевиден. Что делает строка, видно из строки.
|
|
91
94
|
|
|
92
95
|
Многострочный комментарий над каждой функцией — признак того, что объяснение подменило имя.
|
|
93
96
|
Сначала переименовать, потом писать комментарий.
|
|
@@ -102,5 +105,5 @@ description: Паттерн правила doc-style. Брать при напи
|
|
|
102
105
|
«портировано из», ни ссылок на его файлы — нигде.
|
|
103
106
|
- Число написано по памяти, а не пересчитано командой в том же коммите.
|
|
104
107
|
- Пункт плана вычеркнут по памяти о работе, а не по дереву.
|
|
105
|
-
- Формулировка звучит как заголовок, а не как
|
|
108
|
+
- Формулировка звучит как заголовок, а не как правило: «работа со скидками» нарушить нельзя,
|
|
106
109
|
«применяется одна максимальная скидка» — можно.
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: entity-aside
|
|
3
|
+
kind: pattern
|
|
4
|
+
rule: entity-conventions
|
|
5
|
+
description: Паттерн правила entity-conventions. Брать при сборке или правке панели создания и правки записи — готовый маршрут в аутлете ro, наследование общей основы, runMutation, гард несохранённых правок, шапка и футер, уход на связанную запись. Не брать для стора — это паттерн entity-store.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Панель правки записи
|
|
9
|
+
|
|
10
|
+
Паттерн правила `entity-conventions`. Что при этом должно быть верно — закон
|
|
11
|
+
`docs/constitution/entity-editing.md`.
|
|
12
|
+
|
|
13
|
+
## Когда брать
|
|
14
|
+
|
|
15
|
+
- Заводится или правится панель создания и правки записи.
|
|
16
|
+
- Появляется панель без записи — настройки таблицы, лента событий.
|
|
17
|
+
|
|
18
|
+
## Панель объявляется маршрутом в аутлете `ro`
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
{
|
|
22
|
+
path: 'booking/:id',
|
|
23
|
+
outlet: 'ro',
|
|
24
|
+
component: BookingDetailAsideComponent,
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Так панель переживает перезагрузку, передаётся ссылкой и попадает в историю браузера.
|
|
29
|
+
Программного открытия через сервис в админке нет.
|
|
30
|
+
|
|
31
|
+
Панель, которую открывают из шапки, объявляется константой и подмешивается в `children` каждой
|
|
32
|
+
доменной ветки — аутлет стоит в шаблоне хрома, а хром надевает `shell` каждого домена:
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
export const ACTIVITY_ASIDE_ROUTES: Route[] = [{ path: 'activity', outlet: 'ro', component: ActivityFeedAsideComponent }];
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Экран наследует общую основу
|
|
39
|
+
|
|
40
|
+
`RtRouteAsideComponent<T>` держит `entity`, `entityId`, `isCreateMode`, `submitting`,
|
|
41
|
+
`resolving`, `submitError`, открытие панели по маршруту, уход с адреса и всю механику записи.
|
|
42
|
+
Имена из основы не переименовываются: `booking`, `feed`, `slug` вместо `entity` ломают то самое
|
|
43
|
+
единообразие, ради которого основа заведена.
|
|
44
|
+
|
|
45
|
+
## Запись идёт через `runMutation`
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
protected save(): void {
|
|
49
|
+
if (!this.canSave()) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
this.runMutation(this.#store.save(this.#draft()), {
|
|
54
|
+
successKey: 'promoCodeSaved',
|
|
55
|
+
errorText: (): string => this.#store.errorKey() ?? 'promoCodeSaveFailed',
|
|
56
|
+
closeOnSuccess: true,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Занятость, гашение прежней ошибки, тост об успехе и закрытие панели держит основа. `errorText`
|
|
62
|
+
— функция: причина отказа известна только после него. Поток мутации обязан отдать значение или
|
|
63
|
+
ошибку — пустой поток гасит панель навсегда.
|
|
64
|
+
|
|
65
|
+
## Гард несохранённых правок
|
|
66
|
+
|
|
67
|
+
Ставит сама панель, и он встаёт на все четыре пути закрытия: кнопку в шапке, кнопку в футере,
|
|
68
|
+
нажатие мимо панели и Esc.
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
protected readonly panelForm: Signal<NgForm | undefined> = viewChild(NgForm);
|
|
72
|
+
protected readonly formPristine: Signal<boolean> = this.pristineSignal(
|
|
73
|
+
computed((): AbstractControl | undefined => this.panelForm()?.control)
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
constructor() {
|
|
77
|
+
super();
|
|
78
|
+
this.guardUnsavedChanges({ pristine: this.formPristine, save: (): void => this.save() });
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`viewChild` на поле с `#` Angular не принимает — поле объявляется `protected`.
|
|
83
|
+
|
|
84
|
+
## Шапка и футер
|
|
85
|
+
|
|
86
|
+
```html
|
|
87
|
+
<<префикс>-aside-header [title]="title()" [overline]="overline()" [loading]="resolving()" (dismiss)="onClose()">
|
|
88
|
+
<ng-container asideActions>
|
|
89
|
+
<!-- доменные действия иконками; больше двух — под одну кнопку меню -->
|
|
90
|
+
</ng-container>
|
|
91
|
+
</<префикс>-aside-header>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Заголовок называет действие, имя записи идёт надстрочником. В футере две зоны и не больше двух
|
|
95
|
+
кнопок: `asideDismiss` — закрытие, `asidePrimary` — запись. Доменные глаголы в футер не
|
|
96
|
+
ставятся: подтверждение, отказ, снятие с публикации — иконки в шапке.
|
|
97
|
+
|
|
98
|
+
Подписи кнопок закреплены, панель их не выбирает:
|
|
99
|
+
|
|
100
|
+
| Кнопка | Подпись |
|
|
101
|
+
| ------------------------------------ | ------------------------------------------------- |
|
|
102
|
+
| запись при создании | «Создать» |
|
|
103
|
+
| запись при правке | «Сохранить» |
|
|
104
|
+
| закрытие панели, которая записывает | «Закрыть и не сохранять» (`uiCloseWithoutSaving`) |
|
|
105
|
+
| закрытие панели только для просмотра | «Закрыть» |
|
|
106
|
+
|
|
107
|
+
Кнопка записи стоит у противоположного края от кнопки закрытия, а пока идёт запрос —
|
|
108
|
+
показывает спиннер и не нажимается: занятость берётся из `submitting()` основы, своего флага
|
|
109
|
+
панель не заводит. Шапка и футер при прокрутке остаются на месте — прокручивается только зона
|
|
110
|
+
содержимого.
|
|
111
|
+
|
|
112
|
+
## Уход на связанную запись
|
|
113
|
+
|
|
114
|
+
```html
|
|
115
|
+
<a rtElem="related" qa-dataid="promo-code-property-link" [href]="propertyHref()" (click)="openProperty($event)">
|
|
116
|
+
{{ 'propertyOpenLink' | transloco }} <<префикс>-icon name="arrow-right" size="sm" />
|
|
117
|
+
</a>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Адрес даёт `relatedUrl(commands)`, уход — `openRelated(commands)`. `routerLink` здесь не
|
|
121
|
+
годится: директива навигирует сама, `preventDefault` её не останавливает, и вопрос о
|
|
122
|
+
несохранённых правках она обходит.
|
|
123
|
+
|
|
124
|
+
## Частые промахи
|
|
125
|
+
|
|
126
|
+
- Свой `router.navigate` в панели: абсолютные команды меняют только первичную ветку, аутлет
|
|
127
|
+
остаётся в адресе, и роутер отклоняет навигацию молча.
|
|
128
|
+
- Скелетоны по `busy()`, а не по `resolving()`: `busy` включает и запись, и на сохранении поля
|
|
129
|
+
превратились бы в скелетоны.
|
|
130
|
+
- Своё «не найдено» на панели: ненайденная запись уводит с адреса силами основы.
|
|
131
|
+
- Свои отступы поверх общей основы: они дают разную ширину полей на разных панелях и срезают
|
|
132
|
+
обводку фокуса у края прокрутки.
|
|
133
|
+
- Панель, остающаяся открытой после успеха, не сбросила нетронутость (`markAsPristine`) —
|
|
134
|
+
вопрос о правках задаётся сразу после записи.
|
|
135
|
+
- Отключённые поля ввода вместо данных: запись, которую только смотрят, показывается через
|
|
136
|
+
`<dl>`, `<префикс>-detail-list`, `<префикс>-info-item`.
|