chore: Обновить ридми и CI скачивания скилла

This commit is contained in:
2026-08-10 20:44:38 +03:00
parent b34abb37b4
commit ed3d7fb8e0
8 changed files with 294 additions and 52 deletions

View File

@@ -7,8 +7,13 @@ on:
- '.github/workflows/docs.yml' - '.github/workflows/docs.yml'
- 'docs/**' - 'docs/**'
- 'site/**' - 'site/**'
- 'src-skills/**'
- 'skills/**'
- 'scripts/build-skill.mjs'
- 'scripts/check-skill.mjs'
- 'scripts/check-docs.mjs' - 'scripts/check-docs.mjs'
- 'scripts/check-site.mjs' - 'scripts/check-site.mjs'
- 'scripts/lib/skill-bundle.mjs'
- 'scripts/lib/slugify-heading.mjs' - 'scripts/lib/slugify-heading.mjs'
- 'package.json' - 'package.json'
- 'package-lock.json' - 'package-lock.json'
@@ -17,8 +22,13 @@ on:
- '.github/workflows/docs.yml' - '.github/workflows/docs.yml'
- 'docs/**' - 'docs/**'
- 'site/**' - 'site/**'
- 'src-skills/**'
- 'skills/**'
- 'scripts/build-skill.mjs'
- 'scripts/check-skill.mjs'
- 'scripts/check-docs.mjs' - 'scripts/check-docs.mjs'
- 'scripts/check-site.mjs' - 'scripts/check-site.mjs'
- 'scripts/lib/skill-bundle.mjs'
- 'scripts/lib/slugify-heading.mjs' - 'scripts/lib/slugify-heading.mjs'
- 'package.json' - 'package.json'
- 'package-lock.json' - 'package-lock.json'
@@ -49,8 +59,37 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: npm ci run: npm ci
- name: Check documentation - name: Check project
run: npm run check:site run: npm run check
- name: Resolve skill tree hash
id: skill
run: echo "tree_hash=$(git rev-parse HEAD:skills/slm-design)" >> "$GITHUB_OUTPUT"
- name: Restore skill archive
id: skill-cache
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/slm-design.zip
key: slm-design-zip-v1-${{ steps.skill.outputs.tree_hash }}
- name: Pack skill
if: steps.skill-cache.outputs.cache-hit != 'true'
run: >-
git archive
--format=zip
--prefix=slm-design/
--mtime=2000-01-01T00:00:00Z
--output="$RUNNER_TEMP/slm-design.zip"
"${{ steps.skill.outputs.tree_hash }}"
- name: Verify skill archive
run: unzip -t "$RUNNER_TEMP/slm-design.zip"
- name: Add skill archive to Pages
run: |
mkdir -p site/.vitepress/dist/downloads
cp "$RUNNER_TEMP/slm-design.zip" site/.vitepress/dist/downloads/slm-design.zip
- name: Configure Pages - name: Configure Pages
uses: actions/configure-pages@v5 uses: actions/configure-pages@v5

View File

@@ -1,6 +1,8 @@
--- ---
name: rest-client name: rest-client
description: "Используй при создании, изменении или ревью REST API клиента и infra REST-модуля. Триггеры: REST API, REST client, API client, backend API, external API, OpenAPI, Swagger, ручной клиент без OpenAPI, @gromlab/api-codegen, @gromlab/api-codegen@5.1.0, src/infra/*-rest-api, *-rest-api-sdk, REST SDK, npm SDK, client.ts, rest-api.ts, operations-tree.ts, *HttpClient, *RestApi, generated/, operations/, operations/*, data-contracts, hooks/, types/, errors/, HttpClient, ApiRequestClient, RequestParams, ContentType, createApiClient, operationsTree, full client, minimal client, SDK exports, onRequest, onResponse, onError, JWT, refresh token, ApiError, useGet*, get*Key, useSWR, SWRConfiguration, DTO, API error, public API REST-модуля. НЕ используй для любого fetch вне REST-клиента проекта, route-level data fetching Next.js, SLM-архитектуры без REST-модуля, code style, SVG sprites или генерации шаблонов." description: "Используй при создании, изменении или ревью REST API клиента и infra REST-модуля. Триггеры: REST API, REST client, API client, backend API, external API, OpenAPI, Swagger, ручной клиент без OpenAPI, @gromlab/api-codegen, @gromlab/api-codegen@5.1.0, src/infra/*-rest-api, *-rest-api-sdk, REST SDK, npm SDK, client.ts, rest-api.ts, operations-tree.ts, *HttpClient, *RestApi, generated/, operations/, operations/*, data-contracts, hooks/, types/, errors/, HttpClient, ApiRequestClient, RequestParams, ContentType, createApiClient, operationsTree, full client, minimal client, SDK exports, onRequest, onResponse, onError, JWT, refresh token, ApiError, useGet*, get*Key, useSWR, SWRConfiguration, DTO, API error, public API REST-модуля. НЕ используй для любого fetch вне REST-клиента проекта, route-level data fetching Next.js, SLM-архитектуры без REST-модуля, code style, SVG sprites или генерации шаблонов."
metadata:
internal: true
--- ---
<!-- Generated from src/SKILL.md. Do not edit manually. --> <!-- Generated from src/SKILL.md. Do not edit manually. -->

View File

@@ -1,6 +1,8 @@
--- ---
name: slm-design name: slm-design
description: "Экспертная работа с архитектурой SLM Design: проектирование, изменение, миграция и ревью слоёв app/compositions/domains/infra/ui/shared, модулей, доменов, публичных фасетов index/client/browser/server, групп, сегментов, вложенных модулей, зависимостей, состояния и lifecycle. Триггеры: SLM, Scoped Layered Module Design, SLM root, ответственность, владелец, модульная граница, domains vs compositions, доменный контракт, DTO, глубокий импорт, модульный цикл, архитектурное ревью. НЕ применять для обычного code style или локальной правки, не затрагивающей архитектурное решение." description: "Экспертная работа с архитектурой SLM Design: проектирование, изменение, миграция и ревью слоёв app/compositions/domains/infra/ui/shared, модулей, доменов, публичных фасетов index/client/browser/server, групп, сегментов, вложенных модулей, зависимостей, состояния и lifecycle. Триггеры: SLM, Scoped Layered Module Design, SLM root, ответственность, владелец, модульная граница, domains vs compositions, доменный контракт, DTO, глубокий импорт, модульный цикл, архитектурное ревью. НЕ применять для обычного code style или локальной правки, не затрагивающей архитектурное решение."
metadata:
internal: true
--- ---
# SLM Design # SLM Design

View File

@@ -1,6 +1,8 @@
--- ---
name: style-guide name: style-guide
description: "Используй при создании, изменении, форматировании или ревью frontend-кода для соблюдения code style и style guide. Триггеры: JS, TS, JSX, TSX, HTML, CSS, .js, .ts, .jsx, .tsx, .module.css, React-компонент, props, стили, CSS Modules, JSDoc, документация, именование, импорты/экспорты, типизация, отформатировать по гайду, поправить кодстайл. НЕ используй для архитектуры SLM, выбора слоя/модуля/public API, генерации .templates, Next.js routing/data fetching/rendering, настройки PostCSS/tooling, backend-кода и вопросов без правки frontend-кода." description: "Используй при создании, изменении, форматировании или ревью frontend-кода и физическом оформлении уже спроектированных SLM-модулей по code style и style guide. Триггеры: JS, TS, JSX, TSX, HTML, CSS, .js, .ts, .jsx, .tsx, .module.css, React-компонент, Provider, Guard, Error Boundary, props, components/, providers/, modules/, ErrorCode, код ошибки, SCREAMING_SNAKE_CASE, стили, CSS Modules, JSDoc, документация, именование, импорты/экспорты, типизация, отформатировать по гайду, поправить кодстайл. НЕ используй для выбора владельца, слоя, модульной границы или public API по SLM, генерации .templates, Next.js routing/data fetching/rendering, настройки PostCSS/tooling, backend-кода и вопросов без правки frontend-кода; в смешанной задаче сначала примени slm-design."
metadata:
internal: true
--- ---
<!-- Generated from src/SKILL.md. Do not edit manually. --> <!-- Generated from src/SKILL.md. Do not edit manually. -->
@@ -38,6 +40,7 @@ description: "Используй при создании, изменении, ф
| Переменные и функции | `camelCase` | | Переменные и функции | `camelCase` |
| Классы, типы, React-компоненты | `PascalCase` | | Классы, типы, React-компоненты | `PascalCase` |
| Константы верхнего уровня | `SCREAMING_SNAKE_CASE` | | Константы верхнего уровня | `SCREAMING_SNAKE_CASE` |
| Собственные коды ошибок | `SCREAMING_SNAKE_CASE` |
| Хуки | `useSomething` | | Хуки | `useSomething` |
| CSS-классы в CSS Modules | `camelCase` | | CSS-классы в CSS Modules | `camelCase` |
| Enum-ключи | `SCREAMING_SNAKE_CASE` | | Enum-ключи | `SCREAMING_SNAKE_CASE` |
@@ -89,6 +92,57 @@ description: "Используй при создании, изменении, ф
- Имена соответствуют типу сущности и локальному стандарту проекта. - Имена соответствуют типу сущности и локальному стандарту проекта.
- Комментарии объясняют причину или назначение, а не пересказывают код. - Комментарии объясняют причину или назначение, а не пересказывают код.
## Физическая структура SLM
Сначала определи архитектурную роль единицы по правилам `slm-design`. Этот раздел не выбирает владельца и не решает, нужен компонент или вложенный модуль: он задаёт обязательный путь после принятого архитектурного решения.
### Сопоставление единиц с каталогами
- Вложенные framework-компоненты, кроме `Provider`, размещай в `components/`.
- `Guard` и `Error Boundary` считай framework-компонентами и размещай в `components/`.
- Вложенные `Provider` размещай в `providers/`, а не в `components/`.
- Вложенные SLM-модули размещай в `modules/`.
- Внутри модуля не используй `ui/`, `parts/` или другой каталог как альтернативное имя для `components/`, `providers/` или `modules/`.
- Не создавай эти каталоги заранее: добавляй каталог, когда в модуле появляется соответствующая единица.
```text
checkout/
├── index.ts
├── checkout.tsx
├── styles/
├── types/
├── components/
│ ├── order-summary/
│ ├── checkout-guard/
│ └── checkout-error-boundary/
├── providers/
│ └── checkout-events-provider/
└── modules/
└── form-session/
```
### Корневой framework-файл
Один главный framework-файл модуля может находиться непосредственно в корне, если он реализует или собирает ответственность модуля. Исключение распространяется и на главный `Provider`.
Корневой файл не дублируй в `components/` или `providers/`. Остальные компоненты и providers этого модуля размещай в соответствующих каталогах.
### Ограничение вложенности
- Единицы внутри `components/` и `providers/` являются соседями относительно модуля.
- Каталог компонента или Provider не содержит собственные `components/`, `providers/` или `modules/`.
- Следующий структурный уровень создавай только через вложенный модуль в `modules/`.
- Runtime-вложенность JSX не повторяй файловой вложенностью: компонент может рендерить другой компонент, оставаясь его файловым соседом.
### Чеклист структуры SLM
- Архитектурная роль определена до выбора каталога.
- Компоненты, Guards и Error Boundaries находятся в `components/`.
- Вложенные Providers находятся в `providers/`.
- Вложенные модули находятся в `modules/`.
- Главный framework-файл является единственной корневой implementation-единицей модуля.
- Компонентные каталоги не создают рекурсивную файловую иерархию.
## JS/TS ## JS/TS
Применяй этот раздел к `.js`, `.ts` и JS/TS-частям `.jsx` и `.tsx`. Для React-компонентов дополнительно применяй раздел `React и TSX`, для разметки - раздел `HTML, JSX и TSX`. Применяй этот раздел к `.js`, `.ts` и JS/TS-частям `.jsx` и `.tsx`. Для React-компонентов дополнительно применяй раздел `React и TSX`, для разметки - раздел `HTML, JSX и TSX`.
@@ -466,6 +520,28 @@ export type OrderFilters = {
} }
``` ```
#### Коды ошибок
- Собственные коды ошибок проекта записывай в `SCREAMING_SNAKE_CASE` независимо от способа их представления.
- Не переименовывай непрозрачный код внешнего источника: сначала интерпретируй его на границе владельца и сопоставь с собственным кодом проекта.
- Каждый type, объявляющий набор кодов ошибок, документируй многострочным JSDoc.
- Каждый литерал в union кодов ошибок снабжай отдельным JSDoc непосредственно перед литералом.
- Комментарий литерала объясняет ожидаемый исход, условие его возникновения или решение, которое по нему принимает потребитель.
- Не пересказывай в комментарии имя кода и не объединяй несколько кодов одним комментарием.
```ts
/**
* Ожидаемые неуспешные исходы сценариев заказа.
*/
export type OrderErrorCode =
/** Товар изменился после добавления в черновик заказа. */
| 'PRODUCT_CHANGED'
/** Запрошенное количество товара отсутствует на складе. */
| 'INSUFFICIENT_STOCK'
/** Заказ нельзя отменить в его текущем состоянии. */
| 'CANNOT_CANCEL'
```
#### Константы #### Константы
- Документируй константу только если она является публичным контрактом, доменным ограничением, magic value или переиспользуемой конфигурацией. - Документируй константу только если она является публичным контрактом, доменным ограничением, magic value или переиспользуемой конфигурацией.
@@ -534,29 +610,36 @@ export const formatPrice = (value: number): string => {
- Доменные guards размещены рядом с владельцем данных, а не в `shared/lib/value-predicates`. - Доменные guards размещены рядом с владельцем данных, а не в `shared/lib/value-predicates`.
- Импорты типов оформлены через `import type`, а экспорты типов через `export type`. - Импорты типов оформлены через `import type`, а экспорты типов через `export type`.
- Public API не раскрывает implementation details. - Public API не раскрывает implementation details.
- Собственные error codes записаны в `SCREAMING_SNAKE_CASE`, а каждый код имеет отдельный содержательный JSDoc.
- JS/TS-функции, классы, типы, интерфейсы, поля типов, enum, значения enum и константы-контракты документированы по правилам своего подраздела. - JS/TS-функции, классы, типы, интерфейсы, поля типов, enum, значения enum и константы-контракты документированы по правилам своего подраздела.
## React и TSX ## React и TSX
Этот раздел описывает прикладную форму React UI-сущности после того, как архитектура уже определила её место: компонент внутри `ui/` или UI-модуль с корневым `.tsx`. Архитектурные границы компонентов, модулей, сегментов и public API определяет `slm-design`. Форму JSX-разметки дополнительно проверяй по разделу `HTML, JSX и TSX`. Этот раздел описывает прикладную форму React framework-компонента после того, как архитектура уже определила его владельца и место. Правила распространяются на визуальные компоненты, Providers, Guards и Error Boundaries. Архитектурные границы компонентов, модулей, сегментов и public API определяет `slm-design`. Форму JSX-разметки дополнительно проверяй по разделу `HTML, JSX и TSX`.
### Базовая React UI-сущность ### Обязательный обвес framework-компонента
- Используй эту форму для базового React-компонента или UI-модуля с корневым компонентом. - Используй эту форму для каждого React framework-компонента, включая Provider, Guard и Error Boundary.
- Каждый вложенный framework-компонент размещай в отдельной папке согласно разделу `Физическая структура SLM`.
- Держи `.tsx`, props-типы, CSS Module и локальный `index.ts` в отдельных файлах. - Держи `.tsx`, props-типы, CSS Module и локальный `index.ts` в отдельных файлах.
- Файлы структуры обязательны даже для невизуального компонента без собственного DOM: `.tsx`, `types/`, `styles/`, `index.ts`.
- Не объявляй props-типы внутри `.tsx`. - Не объявляй props-типы внутри `.tsx`.
- Не размещай CSS рядом с TSX-кодом: стили живут в `styles/{name}.module.css`. - Не размещай CSS рядом с TSX-кодом: стили живут в `styles/{name}.module.css`.
- Корневой CSS-класс всегда называется `.root`. - Для компонента с собственным DOM корневой CSS-класс называется `.root`.
- Для невизуального компонента создай пустой CSS Module, но не импортируй его до появления стилизуемого DOM.
- Не добавляй Provider, Guard или другой невизуальный компонент DOM-wrapper только ради использования CSS Module.
- Компонент обязан иметь JSDoc-комментарий по React-шаблону. - Компонент обязан иметь JSDoc-комментарий по React-шаблону.
- Всё, что не является React-компонентом, документируй по правилам `Документирование JS/TS`. - Всё, что не является React-компонентом, документируй по правилам `Документирование JS/TS`.
### Структура файлов ### Структура файлов
- Базовая React UI-сущность живёт в собственной папке. - Вложенный framework-компонент живёт в собственной папке.
- Файлы структуры обязательны для новой сущности: `.tsx`, `types/`, `styles/`, `index.ts`.
- Имя файла props-типа строится как `{name}-props.type.ts`. - Имя файла props-типа строится как `{name}-props.type.ts`.
- CSS Module строится как `{name}.module.css`. - CSS Module строится как `{name}.module.css`.
- `index.ts` экспортирует компонент и public props-тип. - Локальный `index.ts` экспортирует компонент и props-тип для использования внутри модуля.
- Единственное исключение из собственной папки — главный framework-файл модуля, включая главный Provider.
- Для главного framework-файла папкой компонента является корень модуля: `styles/` и `types/` создаются непосредственно в нём.
- Корневой `index.ts` остаётся публичным фасетом модуля и экспортирует компонент только через фасет, разрешённый архитектурой и средой выполнения.
```text ```text
user-status/ user-status/
@@ -568,16 +651,29 @@ user-status/
└── index.ts └── index.ts
``` ```
Корневой framework-файл использует тот же обвес без дополнительной папки:
```text
module/
├── index.ts
├── <root-framework-file>.tsx
├── styles/
│ └── {name}.module.css
└── types/
└── {name}-props.type.ts
```
### Типизация props ### Типизация props
- Props-типы выноси в `types/{name}-props.type.ts`. - Props-типы выноси в `types/{name}-props.type.ts`.
- Собственные параметры компонента называй `{Name}Params`. - Собственные параметры компонента называй `{Name}Params`.
- Атрибуты корневого HTML-элемента называй `RootAttrs`. - Атрибуты собственного корневого HTML-элемента называй `RootAttrs`.
- Итоговый тип props называй `{Name}Props`. - Итоговый тип props называй `{Name}Props`.
- `RootAttrs` типизируй через `ComponentPropsWithoutRef<'tag'>`. - Для компонента с собственным DOM типизируй `RootAttrs` через `ComponentPropsWithoutRef<'tag'>`.
- Для Provider или другого компонента без собственного DOM не создавай фиктивный `RootAttrs`.
- Исключай из `RootAttrs` атрибуты, которыми компонент управляет сам: например `children`, если компонент рендерит собственный контент. - Исключай из `RootAttrs` атрибуты, которыми компонент управляет сам: например `children`, если компонент рендерит собственный контент.
- Если собственный параметр конфликтует с HTML-атрибутом, исключай этот атрибут через `Omit`. - Если собственный параметр конфликтует с HTML-атрибутом, исключай этот атрибут через `Omit`.
- Документируй `Params`, `RootAttrs`, `Props` и каждое поле props по правилам `JS/TS`. - Документируй все объявленные `Params`, `RootAttrs`, `Props` и каждое поле props по правилам `JS/TS`.
```ts ```ts
import type { ComponentPropsWithoutRef } from 'react' import type { ComponentPropsWithoutRef } from 'react'
@@ -605,17 +701,20 @@ export type UserStatusProps = RootAttrs & UserStatusParams
### Реализация TSX ### Реализация TSX
- В `.tsx` держи сам компонент, импорт props-типа, импорт CSS Module и импорт функции склейки классов. - В `.tsx` держи сам компонент и импорт props-типа.
- CSS Module и функцию склейки классов импортируй только для компонента с собственным стилизуемым DOM.
- Функцию склейки классов импортируй как `cl`: `import cl from 'clsx'`. - Функцию склейки классов импортируй как `cl`: `import cl from 'clsx'`.
- Компонент объявляй через `const` и именованный экспорт, если framework или локальный стандарт не требует другой формы. - Функциональный компонент объявляй через `const` и именованный экспорт, если framework или локальный стандарт не требует другой формы.
- Нативный React Error Boundary разрешено объявлять классом, потому что React не предоставляет функциональный lifecycle для перехвата ошибок дочернего дерева.
- Не используй `React.FC` по умолчанию. - Не используй `React.FC` по умолчанию.
- Параметр компонента называй `props` и типизируй через `{Name}Props`. - Параметр функционального компонента называй `props` и типизируй через `{Name}Props`.
- Возвращаемый тип компонента не указывай: TypeScript корректно выводит JSX-результат, а явный `ReactElement` сужает допустимые варианты возврата. - Возвращаемый тип компонента не указывай: TypeScript корректно выводит JSX-результат, а явный `ReactElement` сужает допустимые варианты возврата.
- Деструктурируй props внутри тела компонента, а не в сигнатуре. - Деструктурируй props функционального компонента внутри тела, а не в сигнатуре.
- Из props обязательно выделяй `className` и `...rootAttrs`, если корневой элемент принимает HTML-атрибуты. - Из props выделяй `className` и `...rootAttrs`, если компонент имеет собственный корневой DOM-элемент и принимает его HTML-атрибуты.
- Прокидывай `rootAttrs` на корневой DOM-элемент. - Прокидывай `rootAttrs` на собственный корневой DOM-элемент.
- Корневой элемент обязан получить `styles.root` первым CSS-классом. - Собственный корневой DOM-элемент обязан получить `styles.root` первым CSS-классом.
- Внешний `className` добавляй последним аргументом в `cl(...)`. - Внешний `className` добавляй последним аргументом в `cl(...)`.
- Не добавляй невизуальному компоненту DOM-элемент, `className` или `rootAttrs`, если они не нужны его контракту.
- Не создавай вложенный компонент внутри render без причины. - Не создавай вложенный компонент внутри render без причины.
- Не дублируй условия в JSX, если их можно выразить через заранее подготовленную переменную с понятным именем. - Не дублируй условия в JSX, если их можно выразить через заранее подготовленную переменную с понятным именем.
- Для сложной разметки сначала упрощай данные и условия, потом JSX. - Для сложной разметки сначала упрощай данные и условия, потом JSX.
@@ -668,11 +767,13 @@ export const UserStatus = (props: UserStatusProps) => {
### Стили ### Стили
- CSS Module размещай в `styles/{name}.module.css`. - CSS Module всегда создавай в `styles/{name}.module.css`.
- Корневой CSS-класс всегда называй `.root`. - Если компонент имеет собственный DOM, корневой CSS-класс называй `.root`.
- `.root` описывает реальный корневой DOM-элемент компонента. - `.root` описывает реальный корневой DOM-элемент компонента.
- Дополнительные классы описывай рядом с `.root` и подключай через `styles.*`. - Дополнительные классы описывай рядом с `.root` и подключай через `styles.*`.
- Не подменяй `.root` внешним `className`: внешний класс только дополняет `styles.root`. - Не подменяй `.root` внешним `className`: внешний класс только дополняет `styles.root`.
- CSS Module невизуального компонента оставляй пустым и не импортируй, пока у компонента не появится собственный стилизуемый DOM.
- Не создавай DOM-wrapper только для применения `.root`.
```css ```css
.root { .root {
@@ -685,10 +786,11 @@ export const UserStatus = (props: UserStatusProps) => {
### Локальный экспорт ### Локальный экспорт
- В `index.ts` экспортируй компонент и public props-тип. - В локальном `index.ts` экспортируй компонент и props-тип.
- Компонент экспортируй обычным named export. - Компонент экспортируй обычным named export.
- Props экспортируй через `export type`. - Props экспортируй через `export type`.
- Не экспортируй `Params` и `RootAttrs` наружу без необходимости. - Не экспортируй `Params` и `RootAttrs` наружу без необходимости.
- Для корневого framework-файла используй публичный фасет модуля и не обходи его требования к среде выполнения.
```ts ```ts
export { UserStatus } from './user-status' export { UserStatus } from './user-status'
@@ -697,9 +799,10 @@ export type { UserStatusProps } from './types/user-status-props.type'
### Документирование компонентов ### Документирование компонентов
- Каждый React-компонент должен иметь многострочный JSDoc-комментарий. - Каждый React framework-компонент, включая Provider, Guard и Error Boundary, должен иметь многострочный JSDoc-комментарий.
- Комментарий ставь непосредственно перед объявлением компонента. - Комментарий ставь непосредственно перед объявлением компонента.
- Компонент документируй по React-шаблону, а не по шаблону функции из `JS/TS`. - Компонент документируй по React-шаблону, а не по шаблону функции из `JS/TS`.
- Нативный Error Boundary, объявленный классом, также документируй по React-шаблону как компонент.
- Компонент описывает назначение и сценарии применения. - Компонент описывает назначение и сценарии применения.
- Комментарий должен помогать понять, когда использовать компонент, без чтения реализации. - Комментарий должен помогать понять, когда использовать компонент, без чтения реализации.
- В `Используется для` указывай только реальные сценарии применения. - В `Используется для` указывай только реальные сценарии применения.
@@ -737,15 +840,16 @@ export const UserStatus = (props: UserStatusProps) => {
### Чеклист React/TSX ### Чеклист React/TSX
- Базовая React UI-сущность имеет `.tsx`, `types/`, `styles/` и `index.ts`. - Каждый framework-компонент имеет `.tsx`, `types/`, `styles/` и локальный `index.ts`; главный framework-файл использует корень и фасет модуля.
- Props вынесены в `types/{name}-props.type.ts` и собраны из `{Name}Params`, `RootAttrs`, `{Name}Props`. - Props вынесены в `types/{name}-props.type.ts`; `RootAttrs` добавлен только компоненту с собственным DOM.
- Props-типы и поля props документированы по правилам `JS/TS`. - Props-типы и поля props документированы по правилам `JS/TS`.
- Компонент объявлен через `const`, принимает `props` и деструктурирует их внутри тела. - Функциональный компонент объявлен через `const`, принимает `props` и деструктурирует их внутри тела; нативный Error Boundary может быть классом.
- Компонент не использует `React.FC` по умолчанию и не указывает возвращаемый тип без необходимости. - Компонент не использует `React.FC` по умолчанию и не указывает возвращаемый тип без необходимости.
- Корневой DOM-элемент получает `{...rootAttrs}` и `className={cl(styles.root, ..., className)}`. - Собственный корневой DOM-элемент получает `{...rootAttrs}` и `className={cl(styles.root, ..., className)}`.
- CSS Module лежит в `styles/{name}.module.css`, корневой класс называется `.root`. - CSS Module лежит в `styles/{name}.module.css`; у компонента с DOM корневой класс называется `.root`.
- `index.ts` экспортирует компонент и props-тип. - Невизуальный компонент имеет пустой CSS Module без неиспользуемого импорта и искусственного DOM-wrapper.
- Каждый React-компонент имеет комментарий по React-шаблону с назначением и сценариями применения. - Локальный `index.ts` экспортирует компонент и props-тип; корневой компонент экспортируется через подходящий фасет модуля.
- Каждый framework-компонент имеет комментарий по React-шаблону с назначением и сценариями применения.
- Callback props названы через `on*`, внутренние обработчики - через `handle*`. - Callback props названы через `on*`, внутренние обработчики - через `handle*`.
- Named handlers и custom hooks документированы по правилам `JS/TS`; вызовы hooks и inline callbacks не документируются. - Named handlers и custom hooks документированы по правилам `JS/TS`; вызовы hooks и inline callbacks не документируются.
- Hooks вызваны только на верхнем уровне компонента или custom hook. - Hooks вызваны только на верхнем уровне компонента или custom hook.

View File

@@ -1,4 +0,0 @@
interface:
display_name: "Style Guide"
short_description: "Frontend code style, naming and local consistency"
default_prompt: "Use $style-guide to format or review frontend code according to the project style guide and local code conventions."

View File

@@ -1,6 +1,8 @@
--- ---
name: svg-sprites-ru name: svg-sprites-ru
description: "Используй только при настройке, изменении или диагностике @gromlab/svg-sprites. Триггеры: @gromlab/svg-sprites, svg-sprite.config.json, defineSpriteConfig, generateSprite, standalone@server, source: remote, ServerSvgInput, exact modes для standalone, React, Next.js, Vue, Nuxt, Svelte, Angular, Astro, Solid, Preact, Qwik, Lit или Alpine.js, SpriteConfig.input, --input, SpriteViewer и --icon-color-N. НЕ используй для самописных SVG-спрайтов, inline SVG, favicon, растровых изображений, icon fonts или выбора библиотеки иконок." description: "Используй только при настройке, изменении или диагностике @gromlab/svg-sprites. Триггеры: @gromlab/svg-sprites, svg-sprite.config.json, defineSpriteConfig, generateSprite, standalone@server, source: remote, ServerSvgInput, exact modes для standalone, React, Next.js, Vue, Nuxt, Svelte, Angular, Astro, Solid, Preact, Qwik, Lit или Alpine.js, SpriteConfig.input, --input, SpriteViewer и --icon-color-N. НЕ используй для самописных SVG-спрайтов, inline SVG, favicon, растровых изображений, icon fonts или выбора библиотеки иконок."
metadata:
internal: true
--- ---
<!-- Generated from skills/svg-sprites/src/ru/SKILL.md. Do not edit manually. --> <!-- Generated from skills/svg-sprites/src/ru/SKILL.md. Do not edit manually. -->

View File

@@ -1,6 +1,8 @@
--- ---
name: template-generation name: template-generation
description: "Используй при создании, изменении или проверке повторяемой файловой структуры и шаблонов генерации. Триггеры: .templates, @gromlab/create, Template File Generator, scaffold, шаблон, генератор, создать компонент, модуль, layout, screen, widget, business, store, hook, service, page-entry, boilerplate, index.ts, типы, стили, тесты, повторить структуру без copy-paste, настроить генерацию файлов. НЕ используй для одноразовой точечной правки, code style, SLM-архитектуры без генерации файлов, Next.js routing, REST-клиентов или SVG sprites." description: "Используй при создании, изменении или проверке повторяемой файловой структуры и шаблонов генерации. Триггеры: .templates, @gromlab/create, Template File Generator, scaffold, шаблон, генератор, создать компонент, модуль, layout, screen, widget, business, store, hook, service, page-entry, boilerplate, index.ts, типы, стили, тесты, повторить структуру без copy-paste, настроить генерацию файлов. НЕ используй для одноразовой точечной правки, code style, SLM-архитектуры без генерации файлов, Next.js routing, REST-клиентов или SVG sprites."
metadata:
internal: true
--- ---
<!-- Generated from src/SKILL.md. Do not edit manually. --> <!-- Generated from src/SKILL.md. Do not edit manually. -->

129
README.md
View File

@@ -1,33 +1,128 @@
# SLM Design # SLM Design
Документация и agent skill для архитектуры Scoped Layered Module Design. **Scoped Layered Module Design (SLM)** - архитектурная модель для организации кода внутри фронтенд-приложения. Она описывает владельцев поведения, роли слоёв, границы модулей, публичные API и допустимые зависимости.
## Структура Цель SLM - сделать архитектурные решения наблюдаемыми в структуре проекта: понимать, какой модуль отвечает за результат, что доступно его потребителям и как изменение повлияет на остальное приложение.
- `docs/` - документация SLM и единственный источник содержимого сайта и reference-материалов skill. [Документация](https://gromlab-ru.github.io/slm-design/) | [Пример React-приложения](./examples/react-vite/)
- `site/` - VitePress-рендерер: конфигурация, тема и статические ресурсы без собственной копии документации.
- `old-docs/` - архив legacy-документации, не используемый текущим skill.
- `src-skills/` - исходники agent skills.
- `skills/` - собранные skills для установки через `npx skills`.
## Сборка ## AI skill
```bash
npx skills add gromlab-ru/slm-design
```
Или [скачать `slm-design.zip`](https://gromlab-ru.github.io/slm-design/downloads/slm-design.zip).
## О чём SLM
SLM отвечает на три основных вопроса:
1. Какой модуль владеет конкретным результатом или поведением?
2. Какие возможности модуль открывает внешним потребителям?
3. От каких других модулей он может зависеть?
Базовый принцип модели: **у каждой самостоятельной ответственности есть ровно один модуль-владелец**.
Модуль определяет публичный API ответственности, её зависимости, модели и правила, состояние, жизненный цикл и внутреннюю реализацию. Компонент, Provider, hook, store или service остаются механизмами реализации и не становятся отдельными архитектурными владельцами только из-за своей технической роли.
SLM применяется внутри `SLM root` - границы структурной архитектуры одного приложения. Конкретный проект сам сопоставляет свои пути с сущностями SLM.
## Структурная модель
```text
SLM root
└── слой
├── модуль
│ ├── публичные фасеты
│ ├── сегменты
│ └── вложенные модули
└── группа
└── модули
```
| Сущность | Назначение |
|---|---|
| `SLM root` | Ограничивает область архитектуры одним приложением |
| Слой | Классифицирует код по архитектурной роли и ограничивает направления зависимостей |
| Модуль | Владеет одной самостоятельной ответственностью и её публичным API |
| Домен | Специализирует модуль для предметной ответственности и доменных сценариев |
| Группа | Навигационно классифицирует модули, но не владеет кодом или API |
| Сегмент | Организует внутренний код одного модуля без собственной ответственности |
| Вложенный модуль | Владеет отдельной подответственностью внутри родительского модуля |
Слой, группа и сегмент не являются владельцами. По умолчанию код внутри `SLM root` принадлежит ближайшему модулю; исключениями остаются точки входа `app` и небольшие детерминированные ресурсы `shared`.
## Слои
SLM определяет шесть архитектурных ролей:
| Слой | Роль |
|---|---|
| `app` | Запуск приложения, маршруты, преобразование внешних входов и подключение готовых публичных API |
| `compositions` | Представление и связывание готовых возможностей в страницы, макеты, экраны и виджеты |
| `domains` | Предметные ответственности и сценарии: модели, правила, состояние, операции с данными и доменный UI |
| `infra` | Технические сервисы без собственной предметной модели |
| `ui` | Универсальные интерфейсные модули без знания о конкретном продукте или странице |
| `shared` | Детерминированный фундамент без продуктового знания, ввода-вывода и изменяемого состояния |
Проект создаёт только те слои, для которых появился соответствующий код. Пустые слои и обязательное прохождение через каждый промежуточный уровень не требуются.
## Ключевые свойства
- **Один владелец ответственности.** Контракт, состояние, зависимости и внутренняя реализация связного результата принадлежат одному модулю.
- **Закрытая модульная граница.** Внешний код использует модуль только через его публичные фасеты. Глубокие импорты во внутренние файлы запрещены.
- **Фасеты сред выполнения.** Обязательный `index` содержит универсальный API; `client`, `browser` и `server` добавляются только при необходимости.
- **Вертикальные домены.** Домен владеет сценарием целиком: предметным контрактом, правилами, состоянием, ошибками, доменным UI и адаптацией источников данных.
- **Независимость от DTO.** Внешние request, response и error types остаются внутри интеграционной границы и не становятся публичной моделью домена.
- **Ацикличный модульный граф.** Межмодульные импорты проходят через публичный API, учитывают направление слоёв и не образуют циклов.
- **Рост по ответственности.** Сегменты организуют внутренний код, а новый или вложенный модуль появляется только для самостоятельной ответственности.
- **Владение состоянием и ресурсами.** Модуль определяет источник истины, область жизни, число экземпляров и очистку долгоживущих ресурсов.
## Проверка архитектуры
SLM разделяет смысловые и структурные решения.
- На архитектурном ревью проверяются ответственность, единственный владелец, роль слоя, состав публичного API, доменный контракт, состояние и жизненный цикл.
- Автоматически можно проверять направления между слоями, доступ через публичные фасеты, отсутствие глубоких импортов и циклов в модульном графе.
Блокирующие правила собраны в едином реестре и имеют стабильные коды. Рекомендации и примеры объясняют модель, но не подменяют нормативные требования.
## Что SLM не определяет
SLM не требует конкретного фреймворка, state manager, способа получения данных или потока управления. Модель не задаёт фиксированные имена сегментов, полный файловый стайлгайд и правила организации монорепозитория.
Эти решения остаются за проектом. SLM определяет только архитектурный смысл владельцев, границ и зависимостей внутри одного приложения.
## Документация и пример
- [Обзор архитектурной модели](https://gromlab-ru.github.io/slm-design/architecture/)
- [Слои](https://gromlab-ru.github.io/slm-design/architecture/layers)
- [Модули и публичный API](https://gromlab-ru.github.io/slm-design/architecture/modules)
- [Домены и граница внешних данных](https://gromlab-ru.github.io/slm-design/architecture/domains)
- [Зависимости и модульный граф](https://gromlab-ru.github.io/slm-design/architecture/dependencies)
- [Терминология](https://gromlab-ru.github.io/slm-design/reference/terminology)
- [Реестр правил](https://gromlab-ru.github.io/slm-design/rules/registry)
- [Проверка архитектуры](https://gromlab-ru.github.io/slm-design/reference/validation)
- [Пример React + Vite приложения](./examples/react-vite/)
<details>
<summary>Разработка репозитория</summary>
Требуется Node.js 20 или новее. Требуется Node.js 20 или новее.
```bash ```bash
npm ci
npm run build:skill npm run build:skill
npm run check:skill
npm run check:docs
npm run check:site
npm run check npm run check
``` ```
`npm run check:docs` проверяет правила и ссылки документации. `npm run check:site` собирает VitePress из `docs/` и проверяет опубликованные страницы. Skill собирается из `src-skills/slm-design/`, а всё дерево `docs/` рекурсивно включается в `skills/slm-design/reference/docs/`. Собранные файлы не редактируются вручную. Локальный запуск документации:
## Установка
После публикации репозитория:
```bash ```bash
npx skills add gromlab-ru/slm-design --skill slm-design npm run docs:dev
``` ```
Документация находится в `docs/`, исходник skill - в `src-skills/slm-design/`. Собранный каталог `skills/slm-design/` не редактируется вручную.
</details>