chore: Новый черновик DRAFT, удалить старые docs-v

This commit is contained in:
2026-07-30 09:19:59 +03:00
parent 6f6e4896af
commit 590fb63ca7
122 changed files with 29145 additions and 3253 deletions

53
DRAFT/level-1/README.md Normal file
View File

@@ -0,0 +1,53 @@
# SLM Level 1
> Статус: рабочий черновик. Документы в этой папке не являются спецификацией.
Level 1 задаёт основу SLM для лёгких проектов, которым нужна понятная организация без отдельной доменной архитектуры.
## Место в уровнях SLM
| Уровень | Назначение |
|---|---|
| Level 1 | Слои, зависимости, структурные сущности и жизненный цикл ресурсов |
| Level 2 | Слой `domains` для модулей с доменной логикой |
| Level 3 | Строгие правила доменов для крупных и критичных проектов |
Повышение уровня может требовать рефакторинга, но базовые понятия Level 1 сохраняются.
## Область Level 1
Level 1 описывает слои, модули, группы, сегменты, компоненты, публичный API, граф зависимостей и владение жизненным циклом ресурсов.
Level 1 не описывает домены, фабрики, порты, адаптеры, обязательный поток данных, монорепозитории, соглашения об именовании и файловый стайлгайд.
Появление самостоятельной доменной логики является сигналом рассмотреть Level 2.
## Виды утверждений
- **Определение** нормативно задаёт смысл архитектурного термина, но не получает код правила.
- **Правило** задаёт блокирующий архитектурный инвариант и объявляется в каноническом реестре.
- **Рекомендация** помогает принять решение, но не делает архитектуру невалидной.
- **Пример** иллюстрирует модель и не задаёт обязательную структуру.
Нормативные определения находятся в [терминологии](./terminology.md). Канонический набор правил: [правила SLM Level 1](../rules/level-1.md). Формат и требования к ним: [Правила SLM](../rules/).
Остальные документы Level 1 объясняют и иллюстрируют модель, но не владеют точными формулировками определений и правил.
## Основная идея
Модуль является основной архитектурной единицей SLM. Слой задаёт роль и направление зависимостей. Группа помогает навигации, сегмент организует внутреннее содержимое, а компонент всегда принадлежит модулю.
Level 1 требует отдельную папку и единый публичный API модуля. Имена этих элементов, внутренняя файловая форма модулей, сегментов и компонентов определяются стайлгайдом проекта.
## Карта черновика
- [Терминология](./terminology.md)
- [Слои](./layers.md)
- [Зависимости](./dependencies.md)
- [Модули](./modules.md)
- [Группы](./groups.md)
- [Сегменты](./segments.md)
- [Компоненты](./components.md)
- [Вложенные модули](./nested-modules.md)
- [Жизненный цикл](./lifecycle.md)
- [Проверка](./validation.md)

View File

@@ -0,0 +1,65 @@
# Компоненты Level 1
> Пояснение нормативной модели компонентов Level 1.
Компонент является строительным элементом интерфейса, а не самостоятельной архитектурной единицей.
## Связанные правила
- [`SLM-L1-COMPONENT-R009`](../rules/level-1.md#slm-l1-component-r009)
- [`SLM-L1-LAYER-A002`](../rules/level-1.md#slm-l1-layer-a002)
- [`SLM-L1-MODULE-A004`](../rules/level-1.md#slm-l1-module-a004)
- [`SLM-L1-DEPENDENCY-A005`](../rules/level-1.md#slm-l1-dependency-a005)
- [`SLM-L1-MODULE-R011`](../rules/level-1.md#slm-l1-module-r011)
- [`SLM-L1-LIFECYCLE-R013`](../rules/level-1.md#slm-l1-lifecycle-r013)
## Файловая форма
Файловую форму компонента определяет стайлгайд. Компонент может быть одним файлом фреймворка или каталогом со вспомогательными файлами.
```text
landing/
└── ui/
└── hero.tsx
```
```text
landing/
└── ui/
└── hero/
├── hero.tsx
├── styles/
│ └── hero.module.css
└── types/
└── hero-props.type.ts
```
Наличие каталога, типов, стилей или локального `index.ts` не превращает компонент в модуль.
## Реализация
Компонент может отображать входные данные, вызывать переданные обработчики, условно строить интерфейс и хранить локальное состояние представления.
Level 1 не вводит отдельного запрета на импорты, выполняемые кодом компонента. Каждый такой импорт считается зависимостью родительского модуля и должен соблюдать направление слоёв, публичные API и запрет циклов.
Доступ к данным, состояние, контекст или код жизненного цикла внутри компонента сами по себе не создают новую архитектурную границу. Их источники, зависимости и область жизни определяет родительский модуль.
Провайдер может технически реализовывать контекст и жизненный цикл фреймворка, но владельцем состояния и ресурсов остаётся родительский модуль.
Файл в `app` может технически быть компонентом React или Vue. Архитектурно он является точкой входа фреймворка, а не компонентом SLM.
## Компонент и модуль
| Признак | Компонент | Модуль |
|---|---|---|
| Самостоятельная ответственность | Нет | Да |
| Собственный публичный API | Нет | Да |
| Собственная граница зависимостей | Нет | Да |
| Вспомогательные файлы | Может иметь | Может иметь |
| Сегменты и вложенные модули | Нет | Может иметь |
Модуль может состоять всего из одного корневого компонента. Различие определяется владением, а не количеством файлов.
## Когда нужен вложенный модуль
Если часть интерфейса получает самостоятельную ответственность, публичный API, собственную границу зависимостей, область жизни или внутреннюю модульную декомпозицию, она является модулем. При локальном использовании такой модуль может размещаться как вложенный.

View File

@@ -0,0 +1,49 @@
# Зависимости Level 1
> Пояснение нормативной модели зависимостей Level 1.
Слои задают допустимое направление связей, а модули образуют граф зависимостей.
## Что считается зависимостью
- Обычный импорт, импорт типа и реэкспорт одинаково создают архитектурную зависимость.
- Импорт между файлами одного модуля не пересекает модульную границу и не создаёт отдельный узел графа.
- Импорт любого внутреннего файла, сегмента или компонента считается зависимостью ближайшего модуля-владельца.
- Вложенный модуль является обычным самостоятельным узлом графа.
- Группы, сегменты и компоненты не являются самостоятельными узлами графа.
Точка входа фреймворка не является модулем. Её импорты участвуют в проверке направления слоёв, но не образуют исходящий узел графа модулей.
Ресурс `shared` также не является модулем. Его прямой импорт участвует в проверке направления слоёв, но не нарушает требование о публичном API модуля.
## Направление
- Модуль может импортировать модули своего или любого нижнего слоя.
- Модули одного слоя могут импортировать друг друга.
- Промежуточный слой не является обязательным посредником.
Направление слоёв определено в [Слоях](./layers.md).
## Связанные правила
- [`SLM-L1-LAYER-A002`](../rules/level-1.md#slm-l1-layer-a002)
- [`SLM-L1-MODULE-A004`](../rules/level-1.md#slm-l1-module-a004)
- [`SLM-L1-DEPENDENCY-A005`](../rules/level-1.md#slm-l1-dependency-a005)
- [`SLM-L1-NESTED_MODULE-A010`](../rules/level-1.md#slm-l1-nested_module-a010)
## Публичный API
```ts
// Допустимо
import { Button } from '@/ui/button'
// Недопустимо
import { Button } from '@/ui/button/button'
```
## Циклы
```text
ui/modal → ui/button → ui/icon
ui/icon -/→ ui/modal
```

25
DRAFT/level-1/groups.md Normal file
View File

@@ -0,0 +1,25 @@
# Группы Level 1
> Пояснение нормативной модели групп Level 1.
Группа помогает ориентироваться в большом количестве модулей. Она классифицирует структуру, но ничего не реализует и не образует узел графа зависимостей.
## Связанное правило
- [`SLM-L1-GROUP-R007`](../rules/level-1.md#slm-l1-group-r007)
- [`SLM-L1-MODULE-R011`](../rules/level-1.md#slm-l1-module-r011)
## Пример
```text
compositions/
├── pages/ # Группа
│ ├── landing/ # Модуль
│ └── contacts/ # Модуль
└── layouts/ # Группа
└── main/ # Модуль
```
`pages` и `layouts` являются возможной группировкой проекта, а не обязательной структурой Level 1.
Рекомендуется создавать группу только при реальной навигационной потребности. Если папка начинает владеть файлами реализации, состоянием, жизненным циклом или публичным API, она является модулем и должна получить модульную границу.

85
DRAFT/level-1/layers.md Normal file
View File

@@ -0,0 +1,85 @@
# Слои Level 1
> Пояснение нормативной модели слоёв Level 1.
## Базовая структура
```text
src/
├── app/
├── compositions/
├── infra/
├── ui/
└── shared/
```
`src/` здесь является примером SLM root. Фактическую границу определяет устройство приложения.
Отсутствующая в проекте роль не требует пустой папки. Слой является доступной архитектурной ролью, а не обязательным элементом каркаса.
## Роли слоёв
### App
`app` связывает приложение с фреймворком: запускает его, объявляет маршруты, преобразует входные данные и подключает публичные API нижних модулей или ресурсы `shared`. Файлы `app` являются точками входа фреймворка, а не модулями SLM.
Точка входа может напрямую использовать `compositions`, `infra`, `ui` или `shared`, если зависимость разрешена общим порядком слоёв. Такое использование не переносит ответственность нижнего модуля в `app`.
### Compositions
`compositions` содержит продуктовый интерфейс: страницы, макеты, экраны, виджеты, точки входа и другие композиционные модули. Внутреннюю группировку слоя определяет проект.
### Infra
`infra` содержит технические сервисы приложения: аналитику, локализацию, тему, телеметрию и другие возможности среды выполнения без самостоятельной доменной модели.
### UI
`ui` содержит универсальные модули интерфейса, которые не зависят от конкретной страницы или продуктовой композиции.
### Shared
`shared` содержит независимый детерминированный фундамент без знания о продукте, изменяемого состояния и ввода-вывода.
В `shared` допускаются обычные модули и специальные немодульные ресурсы: небольшие чистые утилиты, общие типы, стили, конфигурация и статические файлы. Ресурс не имеет самостоятельной ответственности, публичного API или жизненного цикла и может импортироваться напрямую по пути, установленному стайлгайдом.
Если ресурсу нужны самостоятельная ответственность, собственные архитектурные зависимости, несколько файлов реализации, изменяемое состояние, ввод-вывод или область жизни, он оформляется как модуль. Каталог ресурсов не реэкспортирует модули и не используется для обхода их публичных API.
## Порядок слоёв
```text
app
compositions
infra
ui
shared
```
Код слоя может импортировать модули своего или любого нижнего слоя. Промежуточные слои можно пропускать.
| Слой | Может импортировать нижние слои |
|---|---|
| `app` | `compositions`, `infra`, `ui`, `shared` |
| `compositions` | `infra`, `ui`, `shared` |
| `infra` | `ui`, `shared` |
| `ui` | `shared` |
| `shared` | Нет |
Импорты внутри слоя, публичный API и циклы описаны отдельно в [Зависимостях](./dependencies.md).
## Связанные правила
- [`SLM-L1-LAYER-R001`](../rules/level-1.md#slm-l1-layer-r001)
- [`SLM-L1-LAYER-A002`](../rules/level-1.md#slm-l1-layer-a002)
- [`SLM-L1-LAYER-R003`](../rules/level-1.md#slm-l1-layer-r003)
- [`SLM-L1-MODULE-R011`](../rules/level-1.md#slm-l1-module-r011)
## Граница Level 1
Разрешённый импорт не переносит владение. Например, `infra` может использовать `ui`, но продуктовый интерфейс по-прежнему принадлежит `compositions`.
Самостоятельная доменная модель или сценарий являются сигналом рассмотреть Level 2, а не расширять ответственность `shared` или `infra`.

View File

@@ -0,0 +1,31 @@
# Жизненный цикл Level 1
> Пояснение нормативной модели владения ресурсами Level 1.
Жизненный цикл является частью ответственности модуля. Файл, компонент, провайдер или точка входа фреймворка могут технически создавать и останавливать ресурс, но архитектурным владельцем остаётся модуль.
## Связанные правила
- [`SLM-L1-MODULE-R011`](../rules/level-1.md#slm-l1-module-r011)
- [`SLM-L1-LIFECYCLE-R013`](../rules/level-1.md#slm-l1-lifecycle-r013)
## Граница ресурса
Для ресурса определяются:
- модуль-владелец;
- место создания;
- момент начала работы;
- область жизни;
- допустимое число экземпляров;
- способ остановки и очистки.
Ресурс начинает работу не раньше начала своей области жизни и не остаётся активным после её завершения. Подписки, слушатели, таймеры, наблюдатели, запросы и соединения рассматриваются одинаково, если требуют явного завершения или отмены.
## Реализация
Очистку может выполнять сам модуль, компонент, провайдер или фреймворк. Способ реализации не меняет владельца и не переносит ответственность в технический файл.
Одиночный экземпляр на всё приложение допустим только тогда, когда модуль действительно владеет областью жизни приложения или процесса. Размещение экземпляра на уровне файла само по себе этого не доказывает.
Точка входа `app` может запускать или подключать ресурс через публичный API нижнего модуля, но не становится его владельцем.

43
DRAFT/level-1/modules.md Normal file
View File

@@ -0,0 +1,43 @@
# Модули Level 1
> Пояснение нормативной модели модулей Level 1.
Модуль является основной архитектурной единицей SLM. Он размещается в отдельной папке, но может состоять только из публичной точки входа и одного файла реализации.
## Связанные правила
- [`SLM-L1-MODULE-A004`](../rules/level-1.md#slm-l1-module-a004)
- [`SLM-L1-MODULE-A014`](../rules/level-1.md#slm-l1-module-a014)
- [`SLM-L1-MODULE-R006`](../rules/level-1.md#slm-l1-module-r006)
- [`SLM-L1-MODULE-R011`](../rules/level-1.md#slm-l1-module-r011)
- [`SLM-L1-MODULE-R012`](../rules/level-1.md#slm-l1-module-r012)
## Владение
Каждая самостоятельная ответственность имеет одного модуля-владельца. Модуль определяет её публичный API, зависимости, состояние, область жизни и внутреннее устройство независимо от того, в каком файле выполняется конкретный код.
Точки входа `app` и нормативные ресурсы `shared` являются единственными немодульными исключениями. Остальной код внутри SLM root либо принадлежит существующему модулю, либо образует новый модуль.
## Публичный API
Модуль предоставляет один логический публичный API. Конкретное имя точки входа и механизм экспорта определяет стайлгайд проекта.
Внешний код использует модуль только через публичный API. Сам API открывает только контракт, необходимый реальным внешним потребителям; внутренние механизмы, изменяемое состояние и детали жизненного цикла остаются закрытыми.
## Внутреннее устройство
Модуль может содержать корневые файлы, сегменты, компоненты и [вложенные модули](./nested-modules.md). Внутри своей границы он может использовать относительные импорты и не обязан обращаться к собственному публичному API; точную форму внутренних импортов определяет стайлгайд.
SLM не требует полного каркаса или обязательного каталога сегментов.
## Визуальный модуль
Визуальный модуль обычно имеет корневой компонент, который экспортируется через публичный API.
```text
button/
├── button.tsx
└── index.ts
```
Корневой компонент остаётся компонентом, а владельцем ответственности является модуль `button`.

View File

@@ -0,0 +1,30 @@
# Вложенные модули Level 1
> Пояснение нормативной модели вложенных модулей Level 1.
Вложенный модуль является обычным модулем, размещённым внутри границы родительского модуля. Он имеет собственные ответственность, публичный API и узел графа зависимостей и подчиняется всем общим правилам модулей.
## Связанные правила
- [`SLM-L1-MODULE-A004`](../rules/level-1.md#slm-l1-module-a004)
- [`SLM-L1-MODULE-R006`](../rules/level-1.md#slm-l1-module-r006)
- [`SLM-L1-DEPENDENCY-A005`](../rules/level-1.md#slm-l1-dependency-a005)
- [`SLM-L1-NESTED_MODULE-A010`](../rules/level-1.md#slm-l1-nested_module-a010)
## Пример
```text
landing/
├── landing.page.tsx
├── parts/
│ └── hero/
│ ├── hero.tsx
│ └── index.ts
└── index.ts
```
`parts/` здесь является примером сегмента, а не обязательным именем.
Код родительского модуля использует вложенный модуль через его собственный публичный API. Код за пределами родительского модуля получает доступ только через публичный API родителя.
Если вложенный модуль становится нужен за пределами родителя, рекомендуется перенести его в минимальную общую область без изменения внутренней формы. Доступ через API родителя при этом остаётся допустимым и сам по себе не требует переноса.

29
DRAFT/level-1/segments.md Normal file
View File

@@ -0,0 +1,29 @@
# Сегменты Level 1
> Пояснение нормативной модели сегментов Level 1.
Сегмент организует внутреннее содержимое модуля. Level 1 определяет роль сегмента, но не задаёт обязательный список имён.
## Связанное правило
- [`SLM-L1-SEGMENT-R008`](../rules/level-1.md#slm-l1-segment-r008)
- [`SLM-L1-MODULE-A004`](../rules/level-1.md#slm-l1-module-a004)
## Файловая форма
Названия, набор и содержимое сегментов определяет стайлгайд проекта. Сегмент может группировать файлы, компоненты или вложенные модули.
Файлы и компоненты сегмента принадлежат родительскому модулю. Вложенный модуль внутри сегмента сохраняет собственные ответственность, публичный API и узел графа зависимостей.
## Пример
```text
landing/ # Модуль
└── ui/ # Сегмент модуля
└── hero/ # Каталог компонента
├── hero.tsx
├── styles/ # Вспомогательный каталог компонента
└── types/ # Вспомогательный каталог компонента
```
`styles/` и `types/` внутри каталога компонента не обязаны считаться сегментами SLM. Их форму определяет стайлгайд компонентов.

View File

@@ -0,0 +1,117 @@
# Терминология Level 1
> Нормативные определения рабочего черновика. Этот раздел не объявляет правила.
Определения Level 1 задают обязательный смысл архитектурных терминов и используются при толковании всех правил. Код получают только блокирующие требования, а не сами определения.
## Базовые понятия
### SLM root
Граница структурной архитектуры одного приложения. Внутри неё определяются слои, модули и граф зависимостей Level 1. Монорепозиторий, пакеты и отношения между несколькими SLM root находятся за пределами Level 1.
### Ответственность
Связная часть приложения с одной причиной изменяться. Ответственность является самостоятельной, когда ей нужны собственные публичный API, зависимости, состояние или область жизни.
### Владелец
Модуль, который определяет публичный API ответственности, её зависимости, состояние, область жизни и внутреннее устройство. Место выполнения кода не переносит владение.
### Публичный API
Единая логическая точка внешнего доступа к модулю. Публичный API скрывает внутреннее устройство; конкретное имя файла и механизм экспорта определяет стайлгайд проекта.
### Зависимость
Статическая связь внутри одного SLM root, которую импорт или реэкспорт создаёт между архитектурными границами. Обычный импорт, импорт типа и реэкспорт одинаково создают архитектурную зависимость.
Зависимость любого внутреннего файла, сегмента или компонента относится к ближайшему модулю-владельцу. Вложенный модуль начинает собственную границу и становится отдельным узлом графа зависимостей.
### Область жизни
Период, в течение которого принадлежащие модулю состояние или долгоживущий ресурс должны оставаться активными.
### Ресурс жизненного цикла
Ресурс, работа которого продолжается после первоначального вызова и требует остановки, отмены, отписки или освобождения. Например, подписка, слушатель событий, таймер, наблюдатель, запрос или соединение.
### Очистка
Гарантированное прекращение работы ресурса не позже завершения его области жизни. Автоматическая очистка фреймворка считается очисткой владельца, если модуль устанавливает и контролирует соответствующую границу.
## Структурные сущности
### Слой
Одна из пяти верхнеуровневых ролей внутри SLM root:
| Слой | Роль |
|---|---|
| `app` | Связь приложения с фреймворком: запуск, маршруты и преобразование входных данных |
| `compositions` | Сборка продуктового интерфейса: страницы, макеты, экраны, виджеты и другие композиции |
| `infra` | Технические сервисы и возможности приложения |
| `ui` | Универсальные модули интерфейса без зависимости от конкретной продуктовой композиции |
| `shared` | Независимый детерминированный фундамент без знания о продукте, изменяемого состояния и ввода-вывода |
Слои образуют линейный порядок `app → compositions → infra → ui → shared`. Нижним считается любой слой справа от исходного; промежуточный слой не является обязательным посредником.
### Модуль
Минимальная самостоятельная архитектурная единица Level 1. Модуль владеет одной связной ответственностью, размещается в отдельной папке и предоставляет публичный API.
### Группа
Навигационная папка для модулей и других групп. Группа не является владельцем ответственности, состояния, области жизни, публичного API или узла графа зависимостей.
### Сегмент
Внутренняя часть одного модуля, которая группирует его содержимое по назначению. Сегмент не является самостоятельным владельцем, публичным API или узлом графа зависимостей.
### Компонент
Сущность фреймворка, которая реализует часть интерфейса родительского модуля. Компонент не образует собственного владельца, публичного API или узла графа зависимостей.
Импорты, состояние, доступ к данным и код жизненного цикла компонента принадлежат родительскому модулю. Их наличие само по себе не создаёт новый модуль; решающим признаком является самостоятельная ответственность.
### Вложенный модуль
Обычный модуль, размещённый внутри границы родительского модуля. Он имеет собственные ответственность, публичный API и узел графа зависимостей и подчиняется всем общим правилам модулей.
Публичный API вложенного модуля доступен коду родительской границы. Для кода за пределами родительского модуля вложенный модуль остаётся внутренней реализацией родителя.
### Точка входа фреймворка
Специальная немодульная единица слоя `app`, которая непосредственно связывает приложение с фреймворком. Её импорты участвуют в проверке направления слоёв, но сама точка входа не является узлом графа модулей.
### Ресурс shared
Специальная немодульная единица слоя `shared`: небольшая детерминированная утилита, общий тип, стиль, конфигурация или статический ресурс без продуктового знания, изменяемого состояния, ввода-вывода, области жизни и собственного публичного API.
Ресурс `shared` может импортироваться напрямую по пути, установленному стайлгайдом, и не является узлом графа модулей. Доступный по этому пути файл является всей единицей и не скрывает отдельное внутреннее устройство.
Если ресурсу нужны самостоятельная ответственность, собственные архитектурные зависимости, несколько файлов реализации, изменяемое состояние, ввод-вывод или область жизни, он оформляется как модуль.
## Структурная модель
```text
SLM root
├── app
│ └── точка входа фреймворка
├── compositions | infra | ui
│ ├── группа
│ │ └── модуль
│ └── модуль
│ ├── корневые файлы
│ ├── сегмент
│ │ ├── файлы
│ │ ├── компоненты
│ │ └── вложенные модули
│ └── вложенный модуль
└── shared
├── группа
├── модуль
└── ресурс shared
```
Путь и имя папки сами по себе не определяют сущность. Её определяют ответственность, владелец и публичная граница. Физическое сопоставление путей с сущностями задаётся стайлгайдом или конфигурацией проверки проекта.

View File

@@ -0,0 +1,23 @@
# Проверка Level 1
> Граница автоматической проверки и архитектурного ревью Level 1.
## Автоматическая проверка
Проект, заявляющий соответствие Level 1, сопоставляет физические пути с SLM root, слоями, модулями, вложенными модулями, публичными точками входа, точками входа `app` и ресурсами `shared`. Такое сопоставление задаётся стайлгайдом или конфигурацией проверки и не изменяет нормативный смысл сущностей.
Каждое правило класса `A` должно быть реализовано проверкой проекта и блокировать её при нарушении. Level 1 не навязывает конкретный инструмент.
Скрипт `draft-rules.js` проверяет только целостность документов: формат и уникальность кодов, ссылки и наличие тематических упоминаний. Он не проверяет архитектуру приложения.
Актуальный список правил скрипт получает из [канонического реестра](../rules/level-1.md).
## Архитектурное ревью
Правила класса `R` проверяются вручную. Статический анализ может обнаружить подозрительный код, но не способен окончательно определить:
- ответственность и её владельца;
- соответствие кода роли слоя;
- необходимость экспортов публичного API;
- область жизни ресурса и достаточность очистки;
- наличие самостоятельной границы у компонента, группы или сегмента.