@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,48 +2,76 @@
|
|
|
2
2
|
name: platform-access
|
|
3
3
|
kind: rule
|
|
4
4
|
law: frontend-application
|
|
5
|
-
description: Правило под
|
|
5
|
+
description: Правило под «Закон о фронтовом приложении». Брать, когда правка задевает глобальный объект или среду исполнения — window, globalThis, PLATFORM_ID, isPlatformBrowser, document.defaultView, localStorage, IntersectionObserver. Называет токены DI, приведение типа и подводные камни отдачи страницы сервером. Не действует под libs/api и apps/api. Готовый код — в паттерне platform-access-di.
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
# Окружение браузера —
|
|
8
|
+
# Окружение браузера — как это устроено здесь
|
|
9
9
|
|
|
10
|
-
Правило под закон `
|
|
11
|
-
здесь —
|
|
12
|
-
|
|
13
|
-
`angular-patterns`, файл компонента — `component-structure`, оформление — `styling-bem`, слой
|
|
10
|
+
Правило под закон `docs/constitution/frontend-application.md`. Закон говорит, что должно быть
|
|
11
|
+
верно; здесь — чем в этом дереве заменяется прямое обращение к глобальному объекту. Состояние
|
|
12
|
+
— `angular-patterns`, файл компонента — `component-structure`, стили — `styling-bem`, слой
|
|
14
13
|
обращения к серверу — `api-layer`. Все пять под одним законом.
|
|
15
14
|
|
|
16
|
-
Правило про фронт:
|
|
17
|
-
|
|
15
|
+
Правило про фронт: `libs/api/**` и `apps/api/**` — это NestJS, там своя среда, и ничего из
|
|
16
|
+
перечисленного не применяется.
|
|
18
17
|
|
|
19
|
-
##
|
|
18
|
+
## Как это называется здесь
|
|
20
19
|
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
| Прямое обращение | Здесь |
|
|
21
|
+
| ---------------------------------------- | -------------------------------------------------- |
|
|
22
|
+
| `globalThis.open(...)`, `window.open()` | `inject(WINDOW).open(...)` |
|
|
23
|
+
| `globalThis.crypto.randomUUID()` | `inject(WINDOW).crypto.randomUUID()` |
|
|
24
|
+
| `isPlatformBrowser(inject(PLATFORM_ID))` | `inject(PlatformService).isPlatformBrowser` |
|
|
25
|
+
| `document.defaultView` | `inject(WINDOW)` |
|
|
26
|
+
| прямой `document` | `inject(DOCUMENT)` из `@angular/common` — как было |
|
|
27
|
+
| инициализация DOM после отрисовки | `afterNextRender()` |
|
|
23
28
|
|
|
24
|
-
|
|
29
|
+
`WINDOW`, `PlatformService` и `StorageService` приходят из `@rt-tools/core`.
|
|
25
30
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
## Где это лежит
|
|
32
|
+
|
|
33
|
+
В этом дереве — таблица в `implementation.md` рядом. Пути живут там, а не здесь: правило
|
|
34
|
+
переносится между репозиториями, раскладка — нет, и путь, названный в правиле, врёт в первом
|
|
35
|
+
же дереве, которое держит код иначе.
|
|
36
|
+
|
|
37
|
+
## Как закон применяется здесь
|
|
38
|
+
|
|
39
|
+
- **Глобальный объект приходит токеном `WINDOW`, а не берётся напрямую.** Тип уточняется
|
|
40
|
+
приведением к `Window & typeof globalThis`: конструкторы вроде `IntersectionObserver`
|
|
41
|
+
объявлены на глобальном объекте, а не на интерфейсе `Window`.
|
|
42
|
+
- **Среда проверяется через `PlatformService`, а не через `typeof window`.** Проверка по
|
|
43
|
+
наличию глобала верна случайно и ломается на первой же среде, где глобал подставлен.
|
|
44
|
+
- **Прямое обращение к глобальному объекту отбивает линтер.** Шестнадцать имён окружения
|
|
45
|
+
браузера запрещены на фронтовых деревьях; три места, где прямой доступ осознан, выведены
|
|
46
|
+
из-под запрета списком в конфиге, а не отключением в строке.
|
|
47
|
+
|
|
48
|
+
## Чего из закона здесь нет
|
|
49
|
+
|
|
50
|
+
Запрет действует на имена, а не на пути к ним: `this.#document.defaultView` линтер пропускает,
|
|
51
|
+
потому что глобального имени в такой строке нет. Такое обращение законно — окно там уже пришло
|
|
52
|
+
внедрением, — но и настоящий обход выглядел бы так же, и увидеть его можно только чтением.
|
|
53
|
+
|
|
54
|
+
Прямой доступ остаётся в трёх местах, и это осознанно: встроенный скрипт против мелькания темы
|
|
55
|
+
в `apps/site/src/index.html` (работает до подъёма приложения), обработчик отказа подъёма в
|
|
56
|
+
`apps/*/src/main.ts`, и код внутри `page.evaluate` в сквозных спеках — он исполняется в
|
|
57
|
+
странице, вне DI. Новое место в этот список не добавляется без явного согласования владельца.
|
|
33
58
|
|
|
34
59
|
## Паттерны
|
|
35
60
|
|
|
36
|
-
- `platform-access-di` — готовые
|
|
61
|
+
- `platform-access-di` — готовые инжекты, приведение типа, чистые функции, проверка среды.
|
|
37
62
|
|
|
38
63
|
## Ловушки
|
|
39
64
|
|
|
40
|
-
- **Фабрика токена
|
|
41
|
-
страницы сервером
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
-
|
|
48
|
-
|
|
65
|
+
- **Фабрика токена бросает `Window is not available`, если у документа нет `defaultView`.**
|
|
66
|
+
Под отдачей страницы сервером `defaultView` есть, и инжект полем класса в root-сервисе
|
|
67
|
+
безопасен, но сервис, обязанный работать без DOM вообще, берёт окно внутри метода под
|
|
68
|
+
проверкой среды.
|
|
69
|
+
- **После правки, добавляющей `WINDOW` в сервис, который создаётся на подъёме, нужна не только
|
|
70
|
+
сборка, но и поднятый сервер отдачи страниц.** Сайт — настоящий SSR, и падение видно только
|
|
71
|
+
там.
|
|
72
|
+
- **Вокруг хранилища проверка среды не нужна:** `StorageService` и так уходит в память вне
|
|
73
|
+
браузера, и лишний `if (!isBrowser)` вокруг чтения и записи — мёртвый код.
|
|
74
|
+
- **В `*.logic.ts` и `*.util.ts` нет DI:** окно принимается параметром, а инжектит его
|
|
75
|
+
вызывающий компонент.
|
|
76
|
+
- **Подготавливать состояние сквозной спеки записью в хранилище нельзя:** спека проходит те же
|
|
49
77
|
шаги, что и пользователь.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pricing
|
|
3
|
+
kind: rule
|
|
4
|
+
law: money
|
|
5
|
+
description: Правило под «Закон о деньгах». Брать при правке расчёта цены, скидок, курсов валют, сумм в заказах, письмах и сводках. Называет хранение в целых единицах валюты хранения, единственное округление, выбор одной наибольшей скидки и справочный пересчёт. Готовый код — в паттерне pricing-quote. Чем это названо здесь — в implementation.md рядом.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Суммы — как это устроено здесь
|
|
9
|
+
|
|
10
|
+
Правило под закон `docs/constitution/application/money.md`. Закон говорит, что должно быть
|
|
11
|
+
верно; здесь — каким приёмом это держится. Валюта хранения, набор справочных валют и имена
|
|
12
|
+
колонок — при этом дереве, в `implementation.md` рядом.
|
|
13
|
+
|
|
14
|
+
## Как это называется здесь
|
|
15
|
+
|
|
16
|
+
| В законе | Здесь |
|
|
17
|
+
| ------------- | ---------------------------------------------------------------------------------------------- |
|
|
18
|
+
| сумма | целое число единиц валюты хранения; код валюты стоит в имени поля — `total<Код>`, `price<Код>` |
|
|
19
|
+
| валюта показа | поле заказа с кодом валюты, в которой пользователь смотрел цену |
|
|
20
|
+
| расчёт цены | одна чистая функция: на входе — что заказано, на выходе — подытог, скидка и итог |
|
|
21
|
+
| скидка | механики перечислены в `implementation.md`; правило про выбор одно на все |
|
|
22
|
+
| курс | кэш в хранилище, обновляется по расписанию |
|
|
23
|
+
|
|
24
|
+
## Где это лежит
|
|
25
|
+
|
|
26
|
+
В этом дереве — таблица в `implementation.md` рядом. Пути живут там, а не здесь: правило
|
|
27
|
+
переносится между репозиториями, раскладка — нет, и путь, названный в правиле, врёт в первом
|
|
28
|
+
же дереве, которое держит код иначе.
|
|
29
|
+
|
|
30
|
+
## Как закон применяется здесь
|
|
31
|
+
|
|
32
|
+
- **Сумма хранится в целых единицах валюты хранения.** Дробная часть даёт расхождение между
|
|
33
|
+
подытогом и итогом: показанное построчно перестаёт складываться в показанное внизу. Если
|
|
34
|
+
дробная часть в предметной области значима, единицей хранения становится она сама.
|
|
35
|
+
- **Код валюты стоит в имени поля, а не подразумевается.** Поле `total` без кода читается как
|
|
36
|
+
«сумма вообще», и первый же пересчёт кладёт в него чужую валюту.
|
|
37
|
+
- **Округление происходит один раз — при расчёте цены.** Сумма на экране, сумма в письме и
|
|
38
|
+
сумма в хранилище — одно и то же число, а не три результата одного пересчёта.
|
|
39
|
+
- **Из подходящих скидок применяется одна — наибольшая.** Сравниваются они в валюте хранения:
|
|
40
|
+
доля и сумма иначе несравнимы.
|
|
41
|
+
- **При равной выгоде побеждает та скидка, которую пользователь ввёл руками.** Он ждёт
|
|
42
|
+
подтверждения своему действию, а «код не сработал» при той же итоговой цене читается как
|
|
43
|
+
поломка.
|
|
44
|
+
- **Скидка суммой ограничена подытогом.** Иначе она увела бы цену ниже нуля.
|
|
45
|
+
- **Пересчёт в чужую валюту не хранится.** В заказе лежат сумма в валюте хранения и код валюты
|
|
46
|
+
показа; само число вычисляется на показ.
|
|
47
|
+
- **Оплата идёт в валюте хранения, остальные валюты — справка.** Ни подтверждение, ни документ
|
|
48
|
+
не называют справочное число суммой к оплате.
|
|
49
|
+
- **Валюта показа следует за пользователем.** Он выбрал её на экране — в письме сумма
|
|
50
|
+
пересчитана в неё же.
|
|
51
|
+
- **Курс недоступен — сумма показывается в валюте хранения без пересчёта.** Пересчёт по
|
|
52
|
+
неизвестно какому курсу хуже отсутствующего: отсутствие видно, а неверный курс — нет.
|
|
53
|
+
|
|
54
|
+
## Паттерны
|
|
55
|
+
|
|
56
|
+
- `pricing-quote` — расчёт цены, выбор скидки, работа с курсом.
|
|
57
|
+
|
|
58
|
+
## Ловушки
|
|
59
|
+
|
|
60
|
+
- **Курс тянется по расписанию и кэшируется.** Само число в чужой валюте нигде не сохраняется.
|
|
61
|
+
- **Дробная сумма в контракте — признак того, что округление уехало на показ.** Округление
|
|
62
|
+
одно, и живёт оно в расчёте.
|
|
63
|
+
- **Справочная сумма рядом с суммой к оплате читается как цена.** В письме и в документе
|
|
64
|
+
справочное число подписывается как справка.
|
|
@@ -2,68 +2,82 @@
|
|
|
2
2
|
name: reuse-first
|
|
3
3
|
kind: rule
|
|
4
4
|
law: reuse-first
|
|
5
|
-
description: Правило под
|
|
5
|
+
description: Правило под «Закон о единообразии приложения». Брать перед заведением любого нового экрана, компонента, поля, стора, сервиса, маппера или процедуры — на что опираться, что уже готово в ките и базовых классах, по каким признакам видно, что готовое обошли. Что делать, когда готового не хватило, — в паттерне reuse-first-extend.
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
# Единообразие —
|
|
8
|
+
# Единообразие — как это устроено здесь
|
|
9
9
|
|
|
10
|
-
Правило под закон `
|
|
11
|
-
одинаково; здесь —
|
|
12
|
-
дерево опирается — `implementation.md` рядом.
|
|
10
|
+
Правило под закон `docs/constitution/reuse-first.md`. Закон говорит, что одинаковые вещи ведут
|
|
11
|
+
себя одинаково; здесь — на чём это стоит в этом дереве и чем названо.
|
|
13
12
|
|
|
14
|
-
##
|
|
13
|
+
## Как это называется здесь
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
| В законе | Здесь |
|
|
16
|
+
| -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
17
|
+
| готовое | компоненты кита `@rt-tools/ui-kit-v2` с префиксом `rt-` — сегодня их больше семидесяти — и базовые классы без селектора, наследуемые в `@Component` экрана |
|
|
18
|
+
| раскладка страниц, форм и окон | `apps/<app>/src/styles/`, применяется директивами BEM |
|
|
19
|
+
| оформление части приложения | файл `.scss` рядом с компонентом |
|
|
20
|
+
| отступление, решённое владельцем | маркер `native-ok` в той же строке с объяснением |
|
|
18
21
|
|
|
19
|
-
##
|
|
22
|
+
## Где это лежит
|
|
23
|
+
|
|
24
|
+
В этом дереве — таблица в `implementation.md` рядом. Пути живут там, а не здесь: правило
|
|
25
|
+
переносится между репозиториями, раскладка — нет, и путь, названный в правиле, врёт в первом
|
|
26
|
+
же дереве, которое держит код иначе.
|
|
27
|
+
|
|
28
|
+
## Как закон применяется здесь
|
|
20
29
|
|
|
21
|
-
- **Источник вида выбирается по приложению, а не по привычке.** У дерева может быть больше
|
|
22
|
-
одного источника — свой у каждого приложения; перепутанный приносит на экран форму, которой в
|
|
23
|
-
этом приложении больше нигде нет.
|
|
24
30
|
- **Работа начинается с чтения готового, а не с чистого файла.** Сначала находится опора —
|
|
25
|
-
|
|
26
|
-
Соседний домен читается целиком: приём, который кажется новым, обычно уже написан, а
|
|
27
|
-
переименованный при переносе он перестаёт узнаваться.
|
|
31
|
+
компонент кита, базовый класс, образец в соседнем домене, — потом пишется своё поверх неё.
|
|
28
32
|
- **Свой примитив и своя основа заводятся только с явного одобрения владельца.** Спрашивается
|
|
29
|
-
это до того, как написан первый
|
|
33
|
+
это до того, как написан первый файл.
|
|
30
34
|
- **Панель правки записи наследует общую основу, а не собирается своей разметкой.** Тогда она
|
|
31
35
|
открывается, закрывается и спрашивает про несохранённое одинаково во всех разделах.
|
|
32
36
|
- **Об удаче и об отказе сообщает общая шина, а не своя разметка на экране.** Своё сообщение
|
|
33
37
|
расходится с соседним видом, местом и временем показа.
|
|
34
|
-
- **Компонент объявляется
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
- **У компонента экрана файл стилей по умолчанию пустой.** Раскладка объявлена один
|
|
38
|
-
слое приложения, а экран её только
|
|
39
|
-
- **Готовое расширяется, а не клонируется рядом.** Недостающий вариант заводится в
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
- **Компонент объявляется тремя файлами: `.ts`, `.html`, `.scss`.** `template:` и `styles:` в
|
|
39
|
+
декораторе, атрибут `style=` и правка размеров через `[ngStyle]` — это стили, до которых не
|
|
40
|
+
дотянется ни кит, ни `stylelint`.
|
|
41
|
+
- **У компонента экрана вне кита файл стилей по умолчанию пустой.** Раскладка объявлена один
|
|
42
|
+
раз в общем слое приложения, а экран её только применяет теми же директивами BEM.
|
|
43
|
+
- **Готовое расширяется, а не клонируется рядом.** Недостающий вариант заводится в ките или в
|
|
44
|
+
базовом классе, и его видят остальные экраны.
|
|
45
|
+
- **Накопленное до гарда сосчитано сплошной проверкой и в список только не растёт.** Признаки
|
|
46
|
+
у неё те же, что у гарда, а смотрит она файл целиком: гейт падает на новом месте, старое
|
|
47
|
+
остаётся числом в сводке.
|
|
48
|
+
|
|
49
|
+
## Чего из закона здесь нет
|
|
50
|
+
|
|
51
|
+
Одинаковый ответ поля ввода на ошибку держит кит: `RtFormControlBase` в этом дереве не
|
|
52
|
+
наследует никто, потому что поля берутся его готовыми компонентами. Привязать эту статью
|
|
53
|
+
закона здесь не к чему.
|
|
54
|
+
|
|
55
|
+
Инлайновый шаблон стоит у одного компонента, и у него же единственный `styles:` — это шапка
|
|
56
|
+
админки. `role="alert"` написан руками в шестнадцати шаблонах, а `rt-message` зовёт один
|
|
57
|
+
потребитель. Это долг, а не разрешённое отступление.
|
|
42
58
|
|
|
43
59
|
## Паттерны
|
|
44
60
|
|
|
45
|
-
- `reuse-first-extend` — что делать, когда готового не хватило: расширить
|
|
46
|
-
|
|
61
|
+
- `reuse-first-extend` — что делать, когда готового не хватило: расширить кит, объявить
|
|
62
|
+
отступление маркером, снять его.
|
|
47
63
|
|
|
48
64
|
## Признаки, по которым видно, что готовое обошли
|
|
49
65
|
|
|
50
|
-
- в шаблоне фичи стоит нативный
|
|
51
|
-
- отказ или предупреждение собраны руками —
|
|
52
|
-
- в
|
|
53
|
-
вращения или мерцания;
|
|
54
|
-
- в файле стилей экрана объявлена
|
|
55
|
-
- компонент
|
|
56
|
-
- имя файла кончается на
|
|
57
|
-
|
|
58
|
-
-
|
|
59
|
-
-
|
|
66
|
+
- в шаблоне фичи стоит нативный `<input>`, `<button>`, `<select>`, `<table>` или `<dialog>`;
|
|
67
|
+
- отказ или предупреждение собраны руками — свой `role="alert"` вместо `rt-message`;
|
|
68
|
+
- в `.scss` фичи появились `position: fixed` на весь экран, свой backdrop, `z-index` от тысячи,
|
|
69
|
+
`@keyframes` вращения или мерцания;
|
|
70
|
+
- в файле стилей экрана объявлена раскладка — `display: flex` с `gap` и `padding` на `:host`;
|
|
71
|
+
- компонент реализует `ControlValueAccessor` сам, а не наследует `RtFormControlBase`;
|
|
72
|
+
- имя файла кончается на `-button`, `-input`, `-dialog`, `-spinner` или `-table` вне
|
|
73
|
+
кита;
|
|
74
|
+
- маппер переводит поля вручную, без `BaseMapper`;
|
|
75
|
+
- процедура бэкенда объявлена без `@ConnectProcedure()`.
|
|
60
76
|
|
|
61
77
|
## Ловушки
|
|
62
78
|
|
|
63
|
-
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
-
|
|
67
|
-
|
|
68
|
-
- **Подсказка, зовущая за ненаписанным, останавливает работу.** Пока свой вариант не написан,
|
|
69
|
-
правило зовёт за готовым — а не за тем, что «должно появиться».
|
|
79
|
+
- Перенос переизобретением не считается: строку, которая уже лежит в файле, гард из
|
|
80
|
+
проверяемого текста вычёркивает, а сверка идёт без отступов — при переезде блок меняет
|
|
81
|
+
отступ, оставаясь тем же кодом.
|
|
82
|
+
- Ответ, данный до чтения образца, образец отменяет: согласованная форма выборки списка
|
|
83
|
+
переигрывалась вместе с контрактом через два вопроса после того, как была принята.
|
package/assets/rules/seo.md
CHANGED
|
@@ -2,49 +2,70 @@
|
|
|
2
2
|
name: seo
|
|
3
3
|
kind: rule
|
|
4
4
|
law: search-visibility
|
|
5
|
-
description: Правило под
|
|
5
|
+
description: Правило под «Закон о видимости в поиске». Брать при любой правке, доходящей до разметки публичного сайта — шаблоны страниц, meta/title/description, JSON-LD, canonical, hreflang, маршруты сайта, sitemap, robots, nginx. Называет восемь локалей, где что лежит и чего у нас нет. Готовый код — в паттернах seo-page и seo-verify.
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
# Видимость в поиске —
|
|
8
|
+
# Видимость в поиске — как это устроено здесь
|
|
9
9
|
|
|
10
|
-
Правило под закон `
|
|
11
|
-
здесь —
|
|
12
|
-
канонический путь — `implementation.md` рядом.
|
|
10
|
+
Правило под закон `docs/constitution/application/search-visibility.md`. Закон говорит, что должно быть
|
|
11
|
+
верно; здесь — чем это названо в этом коде, где лежит и что из закона у нас не применяется.
|
|
13
12
|
|
|
14
|
-
##
|
|
13
|
+
## Как это называется здесь
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
| В законе | Здесь |
|
|
16
|
+
| ---------------------------- | ---------------------------------------------------------------------------- |
|
|
17
|
+
| язык страницы | локаль; их восемь — `en`, `ru`, `de`, `zh-Hans`, `zh-Hant`, `ko`, `th`, `hi` |
|
|
18
|
+
| язык по умолчанию | `DEFAULT_LOCALE`, то есть `en`; отдаётся из корня, без префикса в адресе |
|
|
19
|
+
| язык, перевод которого готов | `readyLocales` — поле объекта, а не список локалей сайта |
|
|
20
|
+
| канонический адрес | `${SITE_ORIGIN}${propertyPath(slug, locale)}` |
|
|
21
|
+
| структурированные данные | JSON-LD типа `LodgingBusiness` |
|
|
22
|
+
| прежний адрес страницы | прежний slug объекта |
|
|
18
23
|
|
|
19
|
-
|
|
24
|
+
Локаль по умолчанию отдаётся из корня, остальные — с префиксом `/<код>/`. Префикс — часть
|
|
25
|
+
маршрута, а не часть сборки: `<base href>` в разметке всегда `/`.
|
|
20
26
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
## Где это лежит
|
|
28
|
+
|
|
29
|
+
В этом дереве — таблица в `implementation.md` рядом. Пути живут там, а не здесь: правило
|
|
30
|
+
переносится между репозиториями, раскладка — нет, и путь, названный в правиле, врёт в первом
|
|
31
|
+
же дереве, которое держит код иначе.
|
|
32
|
+
|
|
33
|
+
## Как закон применяется здесь
|
|
34
|
+
|
|
35
|
+
- **Свои теги помечены атрибутом `data-<префикс>-seo`** и при повторном применении переписываются.
|
|
36
|
+
Чужое в `<head>` не трогается: после гидратации там остаются теги от отдачи сервером.
|
|
37
|
+
- **`canonical` ведёт на локализованный путь** `${SITE_ORIGIN}${propertyPath(slug, locale)}`,
|
|
38
|
+
а не на корень и не на адрес локали по умолчанию.
|
|
39
|
+
- **`hreflang` строится по `readyLocales`**, плюс `x-default` на локаль по умолчанию. Список
|
|
40
|
+
локалей сайта для этого не годится: переводы контента заполняет бэк, и готовы они не всегда.
|
|
41
|
+
- **`og:locale:alternate` не включает локаль самой страницы** — иначе она объявлена и
|
|
29
42
|
основной, и альтернативной сразу.
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
|
|
43
|
+
- **`url` в JSON-LD — канонический адрес страницы объекта**, не корень сайта.
|
|
44
|
+
- **Корень локали отдаёт страницу единственного объекта** с каноническим адресом на `/{slug}`;
|
|
45
|
+
посетителя уводит туда nginx ответом 302.
|
|
46
|
+
- **Перенаправление с прежнего адреса отдаётся с `Cache-Control: max-age`** и покрыто
|
|
47
|
+
`proxy_cache_valid 200 301`. Ключ кэша строится без `$args`, поэтому запросы со строкой
|
|
48
|
+
запроса идут мимо кэша (`proxy_cache_bypass` / `proxy_no_cache $is_args`).
|
|
49
|
+
|
|
50
|
+
## Чего из закона здесь нет
|
|
51
|
+
|
|
52
|
+
Листинга объектов нет — корень локали отдаёт единственный объект. Появится листинг —
|
|
53
|
+
канонический адрес корня пересматривается; это `Q-SV-1` в законе.
|
|
33
54
|
|
|
34
55
|
## Паттерны
|
|
35
56
|
|
|
36
|
-
- `seo-page` — правка разметки страницы: теги,
|
|
37
|
-
страница в карте сайта.
|
|
57
|
+
- `seo-page` — правка разметки страницы: теги, JSON-LD, новый маршрут, новая страница в карте.
|
|
38
58
|
- `seo-verify` — проверка отданной разметки на прод-сборке.
|
|
39
59
|
|
|
40
60
|
## Ловушки
|
|
41
61
|
|
|
42
|
-
-
|
|
43
|
-
|
|
44
|
-
-
|
|
45
|
-
|
|
46
|
-
-
|
|
62
|
+
- Тег, добавленный мимо `PropertySeoService`, не помечен `data-<префикс>-seo` — он не будет ни
|
|
63
|
+
переписан, ни удалён при следующем применении и переживёт переход между страницами.
|
|
64
|
+
- Новый маршрут сайта без ветки в `app.routes.ts` под каждую локаль существует только в
|
|
65
|
+
локали по умолчанию: `/de/<путь>` отдаст 404 и поисковику, и гостю.
|
|
66
|
+
- Новая страница не попадает в `sitemap.xml` сама — карта строится из объектов, а не из
|
|
47
67
|
маршрутов.
|
|
48
|
-
-
|
|
49
|
-
|
|
50
|
-
|
|
68
|
+
- Адрес режется по **первому** `?` и только им: `req.url.split('?')` теряет всё после второго
|
|
69
|
+
знака, и перенаправление приходит на страницу без UTM-хвоста — источник заявки считается
|
|
70
|
+
неверно. Разрез живёт в `splitRequestUrl`
|
|
71
|
+
(слой `util` домена страницы объекта) и покрыт спеками; свой не заводить.
|
|
@@ -2,34 +2,58 @@
|
|
|
2
2
|
name: shared-code
|
|
3
3
|
kind: rule
|
|
4
4
|
law: shared-code
|
|
5
|
-
description: Правило под
|
|
5
|
+
description: Правило под «Закон об общем коде приложений». Брать, когда значение должно одинаково пониматься сайтом, админкой и бэкендом — предел выборки, набор операторов условия, направление порядка, длина поля, форма запроса и ответа списка. Называет, что берётся из @rt-tools/utils, что из @<область>/common/util и что ловит check:dupes. Готовый код — в паттерне shared-code-new.
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
# Общий код —
|
|
8
|
+
# Общий код — как это устроено здесь
|
|
9
9
|
|
|
10
|
-
Правило под закон `
|
|
11
|
-
|
|
12
|
-
рядом.
|
|
10
|
+
Правило под закон `docs/constitution/shared-code.md`. Закон говорит, что общим быть обязано;
|
|
11
|
+
здесь — откуда это берётся в этом дереве, чем названо и чего у нас нет.
|
|
13
12
|
|
|
14
|
-
##
|
|
13
|
+
## Как это называется здесь
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
| В законе | Здесь |
|
|
16
|
+
| ------------------------- | --------------------------------------------------------------------------------------------- |
|
|
17
|
+
| общий пакет | `@rt-tools/utils` — собран без фреймворка, зависит от одного `tslib`, грузится под голым Node |
|
|
18
|
+
| общая либа проекта | `@<область>/common/util`; её тег входит в набор `UNIVERSAL` и виден всем трём приложениям |
|
|
19
|
+
| число-настройка | `DEFAULT_PAGE_SIZE`, `MAX_PAGE_SIZE` |
|
|
20
|
+
| набор значений | `FILTER_OPERATOR_TYPE_ENUM`, `LIST_SORT_ORDER_ENUM` |
|
|
21
|
+
| сверка значения с набором | `listSortOrderOf`, `listFilterOperatorOf` |
|
|
22
|
+
| выборка списка | `IPageModel`, `ISortModel`, `IFilterModel`, `IListState` |
|
|
18
23
|
|
|
19
|
-
##
|
|
24
|
+
## Где это лежит
|
|
20
25
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
В этом дереве — таблица в `implementation.md` рядом. Пути живут там, а не здесь: правило
|
|
27
|
+
переносится между репозиториями, раскладка — нет, и путь, названный в правиле, врёт в первом
|
|
28
|
+
же дереве, которое держит код иначе.
|
|
29
|
+
|
|
30
|
+
## Как закон применяется здесь
|
|
31
|
+
|
|
32
|
+
- **Число-настройка лежит в `libs/common/util` и оттуда берётся обеими сторонами.** Умолчание
|
|
33
|
+
доводом не передаётся: пока довод есть, домен вправе назвать своё число, и у промокодов так
|
|
34
|
+
появилось `25` против `20` у остальных.
|
|
35
|
+
- **Набор значений из `@rt-tools/utils` заново не объявляется.** Своё перечисление с теми же
|
|
25
36
|
членами считается копией, даже если имена разошлись.
|
|
26
|
-
- **Значение из набора сверяется
|
|
27
|
-
отбивает запрос
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
- **Перечисления полей порядка и отбора домена копией не считаются.**
|
|
32
|
-
которым сортирует сервер именно этого
|
|
37
|
+
- **Значение из набора сверяется парой общих функций, а промах разбирает вызывающий.** Сервер
|
|
38
|
+
отбивает запрос `InvalidArgument`, экран берёт умолчание.
|
|
39
|
+
- **Общим стал только маппер страницы.** У сторон разная политика на непонятное значение, и
|
|
40
|
+
общим может быть лишь то, где она одна: номер меньше единицы обе стороны читают как первую
|
|
41
|
+
страницу.
|
|
42
|
+
- **Перечисления полей порядка и отбора домена копией не считаются.** `EActivitySortProperty`
|
|
43
|
+
и подобные повторяют имена, по которым сортирует сервер именно этого домена.
|
|
44
|
+
- **Строковая настройка и таблица соответствий сверяются по значению, а не по имени.** Имя
|
|
45
|
+
здесь не ключ: `BEM_BLOCK` и `LOG_CONTEXT` объявлены десятками, и значения у них свои, а
|
|
46
|
+
один и тот же перевод статуса живёт под тремя разными именами.
|
|
47
|
+
|
|
48
|
+
## Чего из закона здесь нет
|
|
49
|
+
|
|
50
|
+
Перевод сущности устроен по-разному: фронт переводит наследником `BaseMapper`, бэкенд —
|
|
51
|
+
свободными функциями `xxxToProto` без общей основы. Это долг `Q-S-1`, а не выбор: новый код на
|
|
52
|
+
бэкенде общей основы не заводит, но и своей второй не пишет.
|
|
53
|
+
|
|
54
|
+
Найденные совпадения строк и таблиц приняты долгом целиком: перевод статуса брони в контракт
|
|
55
|
+
лежит тремя копиями, набор принимаемых вложений — двумя, имя события правки — тремя.
|
|
56
|
+
Сокращать это — работа по доменам, и она заведена вопросом `Q-S-3`.
|
|
33
57
|
|
|
34
58
|
## Паттерны
|
|
35
59
|
|
|
@@ -37,9 +61,10 @@ description: Правило под закон «Общий код приложе
|
|
|
37
61
|
|
|
38
62
|
## Ловушки
|
|
39
63
|
|
|
40
|
-
-
|
|
41
|
-
|
|
42
|
-
-
|
|
43
|
-
|
|
44
|
-
-
|
|
45
|
-
по
|
|
64
|
+
- `typeCast.getAsType` для сверки с набором не годится: значение вне набора он пишет в консоль
|
|
65
|
+
и возвращает строкой `'unknown'`.
|
|
66
|
+
- Накопленные повторы лежат в `tools/dupes-allowlist.json` под ключом `debt` и отказом не
|
|
67
|
+
считаются — гейт падает только на новом. Список только сокращается.
|
|
68
|
+
- Ту же логику, написанную заново под другим именем, проверка не ловит, и такой проверки не
|
|
69
|
+
будет: две одинаковые по форме проверки из разных доменов копией не считаются. Заметить это
|
|
70
|
+
может только тот, кто читает правку, — так сказано и в законе.
|