Фисирую состояние
This commit is contained in:
@@ -42,7 +42,8 @@
|
|||||||
### Sections
|
### Sections
|
||||||
- `sections/summary.md`
|
- `sections/summary.md`
|
||||||
- `sections/details.md`
|
- `sections/details.md`
|
||||||
- `sections/api-scenario.md`
|
- `sections/tech-use-case.md`
|
||||||
|
- `sections/fr.md`
|
||||||
- `sections/api-contract.md`
|
- `sections/api-contract.md`
|
||||||
- `sections/requirements-format.md`
|
- `sections/requirements-format.md`
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
## Особые правила
|
## Особые правила
|
||||||
|
|
||||||
|
- Во frontmatter обязательно указывать `endpoint` (например: `POST /api/v1/clients/contacts-dgr`).
|
||||||
- Сценарий оформляется как технический use case.
|
- Сценарий оформляется как технический use case.
|
||||||
- Функциональные требования маркируются `FR-*`.
|
- Функциональные требования маркируются `FR-*`.
|
||||||
- Нефункциональные требования маркируются `NFR-*`.
|
- Нефункциональные требования маркируются `NFR-*`.
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ system_analytics_refs: []
|
|||||||
- `module` — модуль или подсистема.
|
- `module` — модуль или подсистема.
|
||||||
- `layer` — слой системы.
|
- `layer` — слой системы.
|
||||||
- `updated_at` хранится в формате `YYYY-MM-DD`.
|
- `updated_at` хранится в формате `YYYY-MM-DD`.
|
||||||
|
- Для документов с `doc_type: api_method` поле `endpoint` является обязательным.
|
||||||
|
|
||||||
## Связи и навигация
|
## Связи и навигация
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
# API Scenario Rules
|
|
||||||
|
|
||||||
## Назначение
|
|
||||||
|
|
||||||
Этот файл описывает, как оформлять подраздел `### Сценарий` в API-документах.
|
|
||||||
|
|
||||||
## Обязательные части
|
|
||||||
|
|
||||||
- название
|
|
||||||
- предусловия
|
|
||||||
- триггер
|
|
||||||
- основной сценарий
|
|
||||||
- альтернативный сценарий
|
|
||||||
- обработка ошибок
|
|
||||||
- постусловие
|
|
||||||
|
|
||||||
## Правила
|
|
||||||
|
|
||||||
- Сценарий должен быть лаконичным.
|
|
||||||
- Сценарий должен отражать суть шага.
|
|
||||||
- Сложные технические детали надо выносить в `FR-*`.
|
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
# Functional requrements rules
|
||||||
|
|
||||||
|
## Назначение
|
||||||
|
|
||||||
|
Этот файл описывает, как оформлять функциональные требования в подраздел `### Функциональные требования` в документах.
|
||||||
|
|
||||||
|
## Правила
|
||||||
|
- Функциональное требование (FR) расширяет и дополняет шаги, описанные в сценарии.
|
||||||
|
- Функциональное требование (FR) не должно копировать шаг сценария не неся дополнительной информации.
|
||||||
|
- Название функционального требования формируется следующим образом - "FR.<номер>. <Название>", где
|
||||||
|
- <номер> идет инкрементально внутри конкретного документа, начинается с 1.
|
||||||
|
- <Название> - кратко описывает что делает требование, суть действий (от 3 до 7 слов)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Пример целевого описания сценария
|
||||||
|
|
||||||
|
### Примеры названия FR
|
||||||
|
- Получение данных клиента из АС ЕПК
|
||||||
|
- Проверка уровня доступа
|
||||||
|
- Сценарий построения списка связанных предложений
|
||||||
|
|
||||||
|
|
||||||
|
### Примеры описания FR
|
||||||
|
FR.1. Получение данных клиента из АС ЕПК
|
||||||
|
1. Сформировать запрос к эндпоинту POST /api/v1/path/to/resourse в АС ЕПК
|
||||||
|
- Заголовки
|
||||||
|
- <тут идет описание заголовков и того как они формируются>
|
||||||
|
- Параметры запроса
|
||||||
|
- <тут идет описание параметров и того как они формируются>
|
||||||
|
- Тело запроса
|
||||||
|
- <тут идет описание структуры объекта JSON или payload в другмо формате так как это задано требованиями>
|
||||||
|
|
||||||
|
2. Обработать ответ от АС ЕПК
|
||||||
|
Успешный ответ - <взять из описания вызываеого api критерии успешного ответа >
|
||||||
|
Ничего не найдено - <взять из описания вызываеого api критерии успешного овтета, опционально (если применимо)>
|
||||||
|
Ошибка - <взять из описания вызываеого api критерии успешного ответа >
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
# Scenario Rules
|
||||||
|
|
||||||
|
## Назначение
|
||||||
|
|
||||||
|
Этот файл описывает, как оформлять технический USE CASE в подраздел `### Сценарий` в документах.
|
||||||
|
|
||||||
|
## Обязательные части
|
||||||
|
|
||||||
|
- название
|
||||||
|
- предусловия
|
||||||
|
- триггер
|
||||||
|
- основной сценарий
|
||||||
|
- альтернативный сценарий
|
||||||
|
- обработка ошибок
|
||||||
|
- постусловие
|
||||||
|
|
||||||
|
## Правила
|
||||||
|
- Основной и альтернативные сценарии состоят из шагов.
|
||||||
|
|
||||||
|
- Каждый шаг описывается одним предложением не более 15-20 слов, и состоит из двух частей. Первая часть описывает что мы делаем по смыслу, чтобы это было понятно человеку без низкоуровневых технических деталей. Например: авторизует запрос, получает данные клиента, запрашивает справочники. Вторая часть описывает как это реализовано технически - вызывает эндпоинт /path/to/resource в системе <название системы>.
|
||||||
|
|
||||||
|
- В описании шага не должно быть длинных технических деталей. Если техничсекую реализацию нельхзя описатьодним предложенеим (в лимите длины описания шага), то необхлодимо это вынести в отдельное функциональное требование FR.<номер>. <Название> и описать в нем технические детали. А в шаге сослаться на это требование через "Описание приведено в FR.<номер>. <Название>"
|
||||||
|
|
||||||
|
- Для шагов авторизации обязателен доп шаг с описанием обработки ошибки.
|
||||||
|
- Для шагов с интеграцией обязателен доп шаг с описанием обработки ошибки.
|
||||||
|
- Для шагов с проверкой условий обязательны доп шаги с описанием переходов по сценарию.
|
||||||
|
|
||||||
|
- Название "FR.<номер>. <Название>" формируется следующим образом:
|
||||||
|
- <номер> идет инкрементально внутри конкретного документа, начинается с 1.
|
||||||
|
- <Название> - кратко описывает что делает требование, суть действий.
|
||||||
|
|
||||||
|
- Для каждого шага при необходимости нужно прописать логику действий в случае ошибки или если логика шага определяет несколько сценариев разивития при выполнении заданных условий.
|
||||||
|
|
||||||
|
- Для шагов, которые описывают интеграцию с другой системой необходимо указать название точки интеграции (название эндпоинта, название топика и так далее) и сделать ссылку на FR.<номер>. <Название> с описанием шагов интеграции - как сформировать запрос/сообщение, как обработать ответ, политику ретраев.
|
||||||
|
|
||||||
|
- Сценарий собирается из тезисов, приведенных системной аналимтике в свободной формулировке
|
||||||
|
|
||||||
|
- Функциональные требования "FR.<номер>. <Название>" не должны дублировать шагов сценария в use case. Они содержат детали, которые вынесены из юзкейса чтобы не делать его тяжелым. Если шаг юзкейса описывается одним предложением в лимите длины, то FR делать не нужно.
|
||||||
|
|
||||||
|
- FR обязательно описывается для шага с интеграцией
|
||||||
|
- FR Не описывается для шага авторизации.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Пример целевого описания сценария
|
||||||
|
|
||||||
|
### Примеры шагов сценария
|
||||||
|
|
||||||
|
Пример 1
|
||||||
|
- Авторизует запрос пользователя по наличию у него экшена ролевой модели CI02792632.ContactsDGR.Detail
|
||||||
|
- В случае ошибки - завершить сценарий с кодом UNAUTHORIZED
|
||||||
|
|
||||||
|
Пример 2
|
||||||
|
- Запрашивает данные клиента - вызывает /api/v1/clients/{client-id}/info
|
||||||
|
- В случае ошибки - завершить сценарий с кодом CLIENT_INFO_REQUEST_FAIL
|
||||||
|
|
||||||
|
Пример 3
|
||||||
|
- Возвращает ответ в формате <название DTO>
|
||||||
|
|
||||||
|
### Примеры названия FR
|
||||||
|
- Получение данных клиента из АС ЕПК
|
||||||
|
- Проверка уровня доступа
|
||||||
|
- Сценарий построения списка связанных предложений
|
||||||
@@ -8,6 +8,7 @@ module: example_module
|
|||||||
layer: application
|
layer: application
|
||||||
domain: example_domain
|
domain: example_domain
|
||||||
sub_domain: example_subdomain
|
sub_domain: example_subdomain
|
||||||
|
endpoint: POST /api/v1/example
|
||||||
related_docs: []
|
related_docs: []
|
||||||
status: draft
|
status: draft
|
||||||
updated_at: 2026-03-20
|
updated_at: 2026-03-20
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# Documentation Rules V2
|
||||||
|
|
||||||
|
Этот каталог — новая структура правил для DOC_UPDATE/FROM_FEATURE.
|
||||||
|
|
||||||
|
## Цель
|
||||||
|
|
||||||
|
Разделить инструкции на 2 независимых блока:
|
||||||
|
|
||||||
|
1. `types/` — инструкции по структуре конкретных типов документов (`ui_page`, `api_method`, и т.д.).
|
||||||
|
2. `common-elements/` — инструкции по структуре общих элементов страницы (`tech-use-case`, `fr`, и др.).
|
||||||
|
|
||||||
|
## Структура каталога
|
||||||
|
|
||||||
|
- `documentation-rules.md` — верхнеуровневые правила.
|
||||||
|
- `global/` — общие правила оформления и frontmatter.
|
||||||
|
- `types/` — правила по типам документов (вместо `artifact-types/`).
|
||||||
|
- `common-elements/` — правила по общим секциям (вместо `sections/`).
|
||||||
|
- `templates/` — шаблоны документов.
|
||||||
|
|
||||||
|
## Переключение профиля
|
||||||
|
|
||||||
|
Загрузчик поддерживает переключение через env:
|
||||||
|
|
||||||
|
- `DOC_RULES_PROFILE=v2` (по умолчанию) — использовать `doc_rules_v2`.
|
||||||
|
- `DOC_RULES_PROFILE=legacy` — использовать старый каталог `doc_rules`.
|
||||||
|
|
||||||
|
Если `v2` не содержит валидных пар `type + template`, загрузчик автоматически fallback на `doc_rules`.
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# API Contract Rules
|
||||||
|
|
||||||
|
## Назначение
|
||||||
|
|
||||||
|
Этот файл описывает, как оформлять подраздел `## Контракт` в API-документах.
|
||||||
|
|
||||||
|
## Что должно быть описано
|
||||||
|
|
||||||
|
- входные параметры
|
||||||
|
- выходные параметры
|
||||||
|
- JSON-структуры запросов и ответов
|
||||||
|
- обязательность полей
|
||||||
|
- типы полей
|
||||||
|
- ограничения
|
||||||
|
- описание назначения полей
|
||||||
|
- примеры данных
|
||||||
|
- auth
|
||||||
|
- idempotency
|
||||||
|
- timeout
|
||||||
|
- ошибки и их HTTP-коды
|
||||||
|
|
||||||
|
## Правило качества
|
||||||
|
|
||||||
|
Контракт должен быть достаточно формальным, чтобы по нему можно было собрать OpenAPI-спецификацию.
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# Details Section Rules
|
||||||
|
|
||||||
|
## Назначение
|
||||||
|
|
||||||
|
Этот файл задает общие правила для секции `## Details`.
|
||||||
|
|
||||||
|
## Правила
|
||||||
|
|
||||||
|
- `Details` оформляется как `## Details`.
|
||||||
|
- Внутри `Details` используются заголовки уровня `###` и ниже.
|
||||||
|
- Структура Details зависит от типа документа.
|
||||||
|
- В Details не нужно повторно дублировать навигацию и связи, если они уже есть во frontmatter.
|
||||||
|
- Интеграции, ошибки и кодовые привязки должны быть выделены в отдельные подразделы, если они существенны для понимания документа.
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
# Functional requrements rules
|
||||||
|
|
||||||
|
## Назначение
|
||||||
|
|
||||||
|
Этот файл описывает, как оформлять функциональные требования в подраздел `### Функциональные требования` в документах.
|
||||||
|
|
||||||
|
## Правила
|
||||||
|
- Функциональное требование (FR) расширяет и дополняет шаги, описанные в сценарии.
|
||||||
|
- Функциональное требование (FR) не должно копировать шаг сценария не неся дополнительной информации.
|
||||||
|
- Название функционального требования формируется следующим образом - "FR.<номер>. <Название>", где
|
||||||
|
- <номер> идет инкрементально внутри конкретного документа, начинается с 1.
|
||||||
|
- <Название> - кратко описывает что делает требование, суть действий (от 3 до 7 слов)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Пример целевого описания сценария
|
||||||
|
|
||||||
|
### Примеры названия FR
|
||||||
|
- Получение данных клиента из АС ЕПК
|
||||||
|
- Проверка уровня доступа
|
||||||
|
- Сценарий построения списка связанных предложений
|
||||||
|
|
||||||
|
|
||||||
|
### Примеры описания FR
|
||||||
|
FR.1. Получение данных клиента из АС ЕПК
|
||||||
|
1. Сформировать запрос к эндпоинту POST /api/v1/path/to/resourse в АС ЕПК
|
||||||
|
- Заголовки
|
||||||
|
- <тут идет описание заголовков и того как они формируются>
|
||||||
|
- Параметры запроса
|
||||||
|
- <тут идет описание параметров и того как они формируются>
|
||||||
|
- Тело запроса
|
||||||
|
- <тут идет описание структуры объекта JSON или payload в другмо формате так как это задано требованиями>
|
||||||
|
|
||||||
|
2. Обработать ответ от АС ЕПК
|
||||||
|
Успешный ответ - <взять из описания вызываеого api критерии успешного ответа >
|
||||||
|
Ничего не найдено - <взять из описания вызываеого api критерии успешного овтета, опционально (если применимо)>
|
||||||
|
Ошибка - <взять из описания вызываеого api критерии успешного ответа >
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
# Requirements Format Rules
|
||||||
|
|
||||||
|
## Назначение
|
||||||
|
|
||||||
|
Этот файл задает формат для функциональных и нефункциональных требований.
|
||||||
|
|
||||||
|
## Функциональные требования
|
||||||
|
|
||||||
|
- Использовать коды `FR-1`, `FR-2`, `FR-3` и так далее.
|
||||||
|
- Каждое требование должно описывать отдельный обязательный аспект поведения.
|
||||||
|
- Идентификаторы локальны в пределах одного документа.
|
||||||
|
|
||||||
|
## Нефункциональные требования
|
||||||
|
|
||||||
|
- Использовать коды `NFR-1`, `NFR-2`, `NFR-3` и так далее.
|
||||||
|
- Требования должны описывать характеристики качества, ограничения и эксплуатационные свойства.
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# Summary Section Rules
|
||||||
|
|
||||||
|
## Назначение
|
||||||
|
|
||||||
|
Этот файл задает правила для секции `## Summary`.
|
||||||
|
|
||||||
|
## Правила
|
||||||
|
|
||||||
|
- Summary должен быть коротким explain-слоем быстрого контекста.
|
||||||
|
- Summary должен объяснять суть документа без лишних деталей.
|
||||||
|
- Summary должен быть пригоден для explain и быстрого чтения.
|
||||||
|
- Предпочтительный формат: список ключевых фактов `Purpose`, `Actor`, `Trigger`, `Errors`, `Related ...` и т.д.
|
||||||
|
- Для крупных документов допустим более длинный summary, если он остается структурированным.
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
# Scenario Rules
|
||||||
|
|
||||||
|
## Назначение
|
||||||
|
|
||||||
|
Этот файл описывает, как оформлять технический USE CASE в подраздел `### Сценарий` в документах.
|
||||||
|
|
||||||
|
## Обязательные части
|
||||||
|
|
||||||
|
- название
|
||||||
|
- предусловия
|
||||||
|
- триггер
|
||||||
|
- основной сценарий
|
||||||
|
- альтернативный сценарий
|
||||||
|
- обработка ошибок
|
||||||
|
- постусловие
|
||||||
|
|
||||||
|
## Правила
|
||||||
|
- Основной и альтернативные сценарии состоят из шагов.
|
||||||
|
|
||||||
|
- Каждый шаг описывается одним предложением не более 15-20 слов, и состоит из двух частей. Первая часть описывает что мы делаем по смыслу, чтобы это было понятно человеку без низкоуровневых технических деталей. Например: авторизует запрос, получает данные клиента, запрашивает справочники. Вторая часть описывает как это реализовано технически - вызывает эндпоинт /path/to/resource в системе <название системы>.
|
||||||
|
|
||||||
|
- В описании шага не должно быть длинных технических деталей. Если техничсекую реализацию нельхзя описатьодним предложенеим (в лимите длины описания шага), то необхлодимо это вынести в отдельное функциональное требование FR.<номер>. <Название> и описать в нем технические детали. А в шаге сослаться на это требование через "Описание приведено в FR.<номер>. <Название>"
|
||||||
|
|
||||||
|
- Для шагов авторизации обязателен доп шаг с описанием обработки ошибки.
|
||||||
|
- Для шагов с интеграцией обязателен доп шаг с описанием обработки ошибки.
|
||||||
|
- Для шагов с проверкой условий обязательны доп шаги с описанием переходов по сценарию.
|
||||||
|
|
||||||
|
- Название "FR.<номер>. <Название>" формируется следующим образом:
|
||||||
|
- <номер> идет инкрементально внутри конкретного документа, начинается с 1.
|
||||||
|
- <Название> - кратко описывает что делает требование, суть действий.
|
||||||
|
|
||||||
|
- Для каждого шага при необходимости нужно прописать логику действий в случае ошибки или если логика шага определяет несколько сценариев разивития при выполнении заданных условий.
|
||||||
|
|
||||||
|
- Для шагов, которые описывают интеграцию с другой системой необходимо указать название точки интеграции (название эндпоинта, название топика и так далее) и сделать ссылку на FR.<номер>. <Название> с описанием шагов интеграции - как сформировать запрос/сообщение, как обработать ответ, политику ретраев.
|
||||||
|
|
||||||
|
- Сценарий собирается из тезисов, приведенных системной аналимтике в свободной формулировке
|
||||||
|
|
||||||
|
- Функциональные требования "FR.<номер>. <Название>" не должны дублировать шагов сценария в use case. Они содержат детали, которые вынесены из юзкейса чтобы не делать его тяжелым. Если шаг юзкейса описывается одним предложением в лимите длины, то FR делать не нужно.
|
||||||
|
|
||||||
|
- FR обязательно описывается для шага с интеграцией
|
||||||
|
- FR Не описывается для шага авторизации.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Пример целевого описания сценария
|
||||||
|
|
||||||
|
### Примеры шагов сценария
|
||||||
|
|
||||||
|
Пример 1
|
||||||
|
- Авторизует запрос пользователя по наличию у него экшена ролевой модели CI02792632.ContactsDGR.Detail
|
||||||
|
- В случае ошибки - завершить сценарий с кодом UNAUTHORIZED
|
||||||
|
|
||||||
|
Пример 2
|
||||||
|
- Запрашивает данные клиента - вызывает /api/v1/clients/{client-id}/info
|
||||||
|
- В случае ошибки - завершить сценарий с кодом CLIENT_INFO_REQUEST_FAIL
|
||||||
|
|
||||||
|
Пример 3
|
||||||
|
- Возвращает ответ в формате <название DTO>
|
||||||
|
|
||||||
|
### Примеры названия FR
|
||||||
|
- Получение данных клиента из АС ЕПК
|
||||||
|
- Проверка уровня доступа
|
||||||
|
- Сценарий построения списка связанных предложений
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
# Documentation Rules
|
||||||
|
|
||||||
|
Этот каталог оформляет MVP документации проекта в атомарном формате.
|
||||||
|
|
||||||
|
## Базовая структура
|
||||||
|
|
||||||
|
- Каждый документ содержит YAML frontmatter.
|
||||||
|
- В документе должен быть один `H1`, совпадающий с `title`.
|
||||||
|
- Основные разделы оформляются как `## Summary` и `## Details`.
|
||||||
|
- Внутри `Details` используются заголовки уровня `###` и ниже.
|
||||||
|
- Связи, сущности и навигация описываются во frontmatter через `related_docs`, `links`, `entities`, `parent`, `children`.
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
- Краткий explain-слой быстрого контекста.
|
||||||
|
- Должен позволять быстро понять назначение документа без чтения `Details`.
|
||||||
|
- Предпочтительный формат: компактный список ключевых фактов без длинных абзацев.
|
||||||
|
|
||||||
|
## Details
|
||||||
|
|
||||||
|
- Раскрывает полное описание объекта.
|
||||||
|
- Структура `Details` зависит от типа документа.
|
||||||
|
- Сценарии, ограничения, интеграции, ошибки и кодовые привязки должны быть разнесены по отдельным подразделам.
|
||||||
|
|
||||||
|
## API documents
|
||||||
|
|
||||||
|
Для `api_method` внутри `## Details` обязательны разделы:
|
||||||
|
- `### Описание`
|
||||||
|
- `### Сценарий`
|
||||||
|
- `### Функциональные требования`
|
||||||
|
- `### Нефункциональные требования`
|
||||||
|
- `### Контракт`
|
||||||
|
|
||||||
|
Если у метода есть интеграции и ошибки, также обязательны:
|
||||||
|
- `### Интеграции`
|
||||||
|
- `### Ошибки`
|
||||||
|
- `### Связанный код`
|
||||||
|
- `### История изменений`
|
||||||
|
|
||||||
|
### Сценарий
|
||||||
|
|
||||||
|
Сценарий оформляется как технический use case и содержит:
|
||||||
|
- название
|
||||||
|
- предусловия
|
||||||
|
- триггер
|
||||||
|
- основной сценарий
|
||||||
|
- альтернативный сценарий
|
||||||
|
- обработку ошибок
|
||||||
|
- постусловие
|
||||||
|
|
||||||
|
### Требования
|
||||||
|
|
||||||
|
- Функциональные требования маркируются как `FR-1`, `FR-2`, ...
|
||||||
|
- Нефункциональные требования маркируются как `NFR-1`, `NFR-2`, ...
|
||||||
|
- Идентификаторы требований локальны в рамках одного документа.
|
||||||
|
|
||||||
|
### Контракт
|
||||||
|
|
||||||
|
Контракт должен быть пригоден для последующей сборки OpenAPI-спецификации и включать:
|
||||||
|
- входные параметры
|
||||||
|
- выходные параметры
|
||||||
|
- структуру JSON-сообщений
|
||||||
|
- обязательность полей
|
||||||
|
- типы и ограничения
|
||||||
|
- описание полей
|
||||||
|
- правила заполнения
|
||||||
|
- примеры данных
|
||||||
|
- auth
|
||||||
|
- idempotency
|
||||||
|
- timeout
|
||||||
|
- ошибки и их HTTP-коды
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# Documentation System
|
||||||
|
|
||||||
|
## Назначение
|
||||||
|
|
||||||
|
Этот файл задает общую модель документации проекта.
|
||||||
|
|
||||||
|
## Базовая модель
|
||||||
|
|
||||||
|
Каждый документ должен состоять из двух слоев:
|
||||||
|
- YAML frontmatter
|
||||||
|
- контент
|
||||||
|
|
||||||
|
Контент всегда состоит из двух обязательных разделов:
|
||||||
|
- `## Summary`
|
||||||
|
- `## Details`
|
||||||
|
|
||||||
|
Над ними должен быть один заголовок `# <title>`, совпадающий со значением `title` во frontmatter.
|
||||||
|
|
||||||
|
## Принципы
|
||||||
|
|
||||||
|
- Документы должны быть атомарными.
|
||||||
|
- Один документ описывает одну тему.
|
||||||
|
- Вместо дублирования между документами используются явные ссылки.
|
||||||
|
- Связи и навигация должны быть формализованы.
|
||||||
|
- Документы должны быть пригодны для чтения человеком и для RAG.
|
||||||
|
- Документы должны быть пригодны для частичного обновления без деградации структуры.
|
||||||
|
|
||||||
|
## Типы документов
|
||||||
|
|
||||||
|
На уровне проекта поддерживаются типы:
|
||||||
|
- `api_method`
|
||||||
|
- `logic_block`
|
||||||
|
- `architecture_overview`
|
||||||
|
- `domain_entity`
|
||||||
|
- `ui_page`
|
||||||
|
- `integration_doc`
|
||||||
|
- `index_page`
|
||||||
|
- `glossary_item`
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
# Frontmatter Rules
|
||||||
|
|
||||||
|
## Назначение
|
||||||
|
|
||||||
|
Этот файл описывает единый контракт YAML frontmatter для всех документов.
|
||||||
|
|
||||||
|
## Обязательные поля
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
id: string
|
||||||
|
title: string
|
||||||
|
doc_type: string
|
||||||
|
domain: string
|
||||||
|
sub_domain: string
|
||||||
|
related_docs: []
|
||||||
|
status: string
|
||||||
|
```
|
||||||
|
|
||||||
|
## Поля совместимости и рекомендуемые поля
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
type: string
|
||||||
|
name: string
|
||||||
|
module: string
|
||||||
|
layer: string
|
||||||
|
updated_at: YYYY-MM-DD
|
||||||
|
tags: []
|
||||||
|
entities: []
|
||||||
|
parent: string | null
|
||||||
|
children: []
|
||||||
|
links: {}
|
||||||
|
source_of_truth: string
|
||||||
|
related_code: []
|
||||||
|
system_analytics_refs: []
|
||||||
|
```
|
||||||
|
|
||||||
|
## Правила
|
||||||
|
|
||||||
|
- `id` должен быть стабильным и уникальным в пределах документации проекта.
|
||||||
|
- `title` — человекочитаемый заголовок.
|
||||||
|
- `doc_type` — канонический тип документа.
|
||||||
|
- `domain` и `sub_domain` определяют бизнес-контекст документа.
|
||||||
|
- `related_docs` хранит явные связи с другими markdown-документами.
|
||||||
|
- `status` хранит жизненный цикл документа: например `draft`, `approved`, `active`.
|
||||||
|
- `type` допустимо дублировать как alias для tooling-совместимости с индексаторами.
|
||||||
|
- `name` — короткое системное имя документа.
|
||||||
|
- `module` — модуль или подсистема.
|
||||||
|
- `layer` — слой системы.
|
||||||
|
- `updated_at` хранится в формате `YYYY-MM-DD`.
|
||||||
|
|
||||||
|
## Связи и навигация
|
||||||
|
|
||||||
|
- `entities` описывает сущности, связанные с документом.
|
||||||
|
- `parent` и `children` описывают иерархию.
|
||||||
|
- `links` описывает typed graph связей между документами, кодом и интеграциями.
|
||||||
|
|
||||||
|
## Формат links
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
links:
|
||||||
|
called_by:
|
||||||
|
- ext.health_probe
|
||||||
|
uses_logic:
|
||||||
|
- logic.some_flow
|
||||||
|
integrates_with:
|
||||||
|
- ext.some_system
|
||||||
|
```
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
# Linking Rules
|
||||||
|
|
||||||
|
## Назначение
|
||||||
|
|
||||||
|
Этот файл описывает, как связывать документы между собой.
|
||||||
|
|
||||||
|
## Иерархия
|
||||||
|
|
||||||
|
- `parent` используется для родительского документа.
|
||||||
|
- `children` используется для прямых дочерних документов.
|
||||||
|
- Иерархия должна быть осмысленной и стабильной.
|
||||||
|
- Для общей точки входа допустим `index_page`.
|
||||||
|
|
||||||
|
## Графовые связи
|
||||||
|
|
||||||
|
Для `related_docs` используются ссылки на соседние документы.
|
||||||
|
|
||||||
|
Для `links` рекомендуется использовать typed-ключи:
|
||||||
|
- `called_by`
|
||||||
|
- `uses_logic`
|
||||||
|
- `reads_db`
|
||||||
|
- `writes_db`
|
||||||
|
- `integrates_with`
|
||||||
|
- `used_by`
|
||||||
|
- `exposes_api`
|
||||||
|
- `uses_entities`
|
||||||
|
|
||||||
|
## Правила использования
|
||||||
|
|
||||||
|
- Если документ логически входит в другой, использовать `parent`/`children`.
|
||||||
|
- Если связь нужна для навигации между равноправными документами, дублировать ее в `related_docs`.
|
||||||
|
- Если связь отражает поведение, интеграции или переиспользование, фиксировать ее в `links`.
|
||||||
|
- Детальное описание интеграций хранить в body документа, а не только во frontmatter.
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# Naming Rules
|
||||||
|
|
||||||
|
## Назначение
|
||||||
|
|
||||||
|
Этот файл описывает правила именования документов, файлов и идентификаторов.
|
||||||
|
|
||||||
|
## Правила для файлов
|
||||||
|
|
||||||
|
- Имена файлов должны быть в kebab-case.
|
||||||
|
- Имя файла должно отражать одну тему.
|
||||||
|
- Для шаблонов использовать суффикс `.template.md`.
|
||||||
|
|
||||||
|
## Правила для id
|
||||||
|
|
||||||
|
- `id` строится в формате `<type-group>.<name>`.
|
||||||
|
- Примеры:
|
||||||
|
- `api.send_message_endpoint`
|
||||||
|
- `logic.telegram_notification_loop`
|
||||||
|
- `architecture.telegram_notify_app`
|
||||||
|
|
||||||
|
## Правила для title
|
||||||
|
|
||||||
|
- `title` должен быть кратким и человекочитаемым.
|
||||||
|
- В `title` допускаются пробелы и естественный язык.
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Writing Style
|
||||||
|
|
||||||
|
## Назначение
|
||||||
|
|
||||||
|
Этот файл задает правила стиля для текстового наполнения документации.
|
||||||
|
|
||||||
|
## Правила стиля
|
||||||
|
|
||||||
|
- Текст должен быть лаконичным.
|
||||||
|
- Формулировки должны быть точными и техническими.
|
||||||
|
- Summary должен быть кратким explain-слоем.
|
||||||
|
- Details должен раскрывать суть без лишней воды.
|
||||||
|
- Нежелательно смешивать несколько тем в одном документе.
|
||||||
|
- Если детали относятся к другому артефакту, их нужно выносить в отдельный документ.
|
||||||
|
|
||||||
|
## Язык
|
||||||
|
|
||||||
|
- Основной язык документации — русский.
|
||||||
|
- Технические термины, названия классов, API, RAG, OpenAPI, runtime и другие устоявшиеся identifiers можно оставлять на английском.
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
---
|
||||||
|
id: api.example_method
|
||||||
|
type: api_method
|
||||||
|
doc_type: api_method
|
||||||
|
name: example_method
|
||||||
|
title: HTTP API /example
|
||||||
|
module: example_module
|
||||||
|
layer: application
|
||||||
|
domain: example_domain
|
||||||
|
sub_domain: example_subdomain
|
||||||
|
related_docs: []
|
||||||
|
status: draft
|
||||||
|
updated_at: 2026-03-20
|
||||||
|
source_of_truth: code
|
||||||
|
parent: null
|
||||||
|
children: []
|
||||||
|
tags: []
|
||||||
|
entities: []
|
||||||
|
links: {}
|
||||||
|
---
|
||||||
|
|
||||||
|
# HTTP API /example
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
Краткое описание метода.
|
||||||
|
|
||||||
|
## Details
|
||||||
|
|
||||||
|
## Описание
|
||||||
|
|
||||||
|
Короткое описание сути метода.
|
||||||
|
|
||||||
|
## Сценарий
|
||||||
|
|
||||||
|
**Название:**
|
||||||
|
|
||||||
|
**Предусловия:**
|
||||||
|
-
|
||||||
|
|
||||||
|
**Триггер:**
|
||||||
|
-
|
||||||
|
|
||||||
|
**Основной сценарий:**
|
||||||
|
1.
|
||||||
|
|
||||||
|
**Альтернативный сценарий:**
|
||||||
|
1.
|
||||||
|
|
||||||
|
**Обработка ошибок:**
|
||||||
|
1.
|
||||||
|
|
||||||
|
**Постусловие:**
|
||||||
|
-
|
||||||
|
|
||||||
|
## Функциональные требования
|
||||||
|
|
||||||
|
**FR-1.**
|
||||||
|
|
||||||
|
## Нефункциональные требования
|
||||||
|
|
||||||
|
**NFR-1.**
|
||||||
|
|
||||||
|
## Контракт
|
||||||
|
|
||||||
|
### Входные параметры
|
||||||
|
|
||||||
|
| Параметр | Где передается | Тип | Обязательность | Ограничения | Описание | Пример |
|
||||||
|
|---|---|---|---|---|---|---|
|
||||||
|
| | | | | | | |
|
||||||
|
|
||||||
|
### Выходные параметры
|
||||||
|
|
||||||
|
| Поле | Тип | Обязательность | Ограничения | Описание | Заполнение | Пример |
|
||||||
|
|---|---|---|---|---|---|---|
|
||||||
|
| | | | | | | |
|
||||||
|
|
||||||
|
### Интеграции
|
||||||
|
|
||||||
|
### Ошибки
|
||||||
|
|
||||||
|
### Связанный код
|
||||||
|
|
||||||
|
### История изменений
|
||||||
+48
@@ -0,0 +1,48 @@
|
|||||||
|
---
|
||||||
|
id: architecture.example_system
|
||||||
|
type: architecture_overview
|
||||||
|
doc_type: architecture_overview
|
||||||
|
name: example_system
|
||||||
|
title: Обзор архитектуры Example System
|
||||||
|
module: example_module
|
||||||
|
layer: system
|
||||||
|
domain: example_domain
|
||||||
|
sub_domain: example_subdomain
|
||||||
|
related_docs: []
|
||||||
|
status: draft
|
||||||
|
updated_at: 2026-03-20
|
||||||
|
source_of_truth: mixed
|
||||||
|
parent: null
|
||||||
|
children: []
|
||||||
|
tags: []
|
||||||
|
entities: []
|
||||||
|
links: {}
|
||||||
|
---
|
||||||
|
|
||||||
|
# Обзор архитектуры Example System
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
Краткое описание архитектуры.
|
||||||
|
|
||||||
|
## Details
|
||||||
|
|
||||||
|
### Описание
|
||||||
|
|
||||||
|
### Контекст
|
||||||
|
|
||||||
|
### Границы системы
|
||||||
|
|
||||||
|
### Компоненты
|
||||||
|
|
||||||
|
### Интеграционные сценарии
|
||||||
|
|
||||||
|
### Интеграции
|
||||||
|
|
||||||
|
### Ограничения
|
||||||
|
|
||||||
|
### Связанный код
|
||||||
|
|
||||||
|
### Связанные документы
|
||||||
|
|
||||||
|
### История изменений
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
---
|
||||||
|
id: domain.example_entity
|
||||||
|
type: domain_entity
|
||||||
|
doc_type: domain_entity
|
||||||
|
name: example_entity
|
||||||
|
title: Пример доменной сущности
|
||||||
|
module: example_module
|
||||||
|
layer: domain
|
||||||
|
domain: example_domain
|
||||||
|
sub_domain: example_subdomain
|
||||||
|
related_docs: []
|
||||||
|
status: draft
|
||||||
|
updated_at: 2026-03-20
|
||||||
|
source_of_truth: code
|
||||||
|
parent: null
|
||||||
|
children: []
|
||||||
|
tags: []
|
||||||
|
entities: []
|
||||||
|
links: {}
|
||||||
|
---
|
||||||
|
|
||||||
|
# Пример доменной сущности
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
Краткое описание сущности.
|
||||||
|
|
||||||
|
## Details
|
||||||
|
|
||||||
|
### Описание
|
||||||
|
|
||||||
|
### Модель данных
|
||||||
|
|
||||||
|
### Состояния и инварианты
|
||||||
|
|
||||||
|
### Технический use case
|
||||||
|
|
||||||
|
### Функциональные требования
|
||||||
|
|
||||||
|
### Нефункциональные требования
|
||||||
|
|
||||||
|
### Интеграции
|
||||||
|
|
||||||
|
### Связанный код
|
||||||
|
|
||||||
|
### Связанные документы
|
||||||
|
|
||||||
|
### История изменений
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
---
|
||||||
|
id: logic.example_block
|
||||||
|
type: logic_block
|
||||||
|
doc_type: logic_block
|
||||||
|
name: example_block
|
||||||
|
title: Пример блока логики
|
||||||
|
module: example_module
|
||||||
|
layer: application
|
||||||
|
domain: example_domain
|
||||||
|
sub_domain: example_subdomain
|
||||||
|
related_docs: []
|
||||||
|
status: draft
|
||||||
|
updated_at: 2026-03-20
|
||||||
|
source_of_truth: code
|
||||||
|
parent: null
|
||||||
|
children: []
|
||||||
|
tags: []
|
||||||
|
entities: []
|
||||||
|
links: {}
|
||||||
|
---
|
||||||
|
|
||||||
|
# Пример блока логики
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
Краткое описание блока логики.
|
||||||
|
|
||||||
|
## Details
|
||||||
|
|
||||||
|
### Описание
|
||||||
|
|
||||||
|
### Контекст
|
||||||
|
|
||||||
|
### Технический use case
|
||||||
|
|
||||||
|
### Функциональные требования
|
||||||
|
|
||||||
|
### Нефункциональные требования
|
||||||
|
|
||||||
|
### Интеграции
|
||||||
|
|
||||||
|
### Ограничения и условия вызова
|
||||||
|
|
||||||
|
### Ошибки и деградации
|
||||||
|
|
||||||
|
### Связанные API
|
||||||
|
|
||||||
|
### Связанный код
|
||||||
|
|
||||||
|
### История изменений
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
---
|
||||||
|
id: ui.example_page
|
||||||
|
type: ui_page
|
||||||
|
doc_type: ui_page
|
||||||
|
name: example_page
|
||||||
|
title: Пример UI-страницы
|
||||||
|
module: example_module
|
||||||
|
layer: presentation
|
||||||
|
domain: example_domain
|
||||||
|
sub_domain: example_subdomain
|
||||||
|
related_docs: []
|
||||||
|
status: draft
|
||||||
|
updated_at: 2026-03-20
|
||||||
|
source_of_truth: mixed
|
||||||
|
parent: null
|
||||||
|
children: []
|
||||||
|
tags: []
|
||||||
|
entities: []
|
||||||
|
links: {}
|
||||||
|
---
|
||||||
|
|
||||||
|
# Пример UI-страницы
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
Краткое описание страницы и её назначения.
|
||||||
|
|
||||||
|
## Details
|
||||||
|
|
||||||
|
### Назначение страницы
|
||||||
|
|
||||||
|
### Пользовательский сценарий
|
||||||
|
|
||||||
|
### Основные блоки интерфейса
|
||||||
|
|
||||||
|
### Связанные API и сущности
|
||||||
|
|
||||||
|
### Функциональные требования
|
||||||
|
|
||||||
|
### Нефункциональные требования
|
||||||
|
|
||||||
|
### Ограничения и граничные случаи
|
||||||
|
|
||||||
|
### Ошибки и валидации
|
||||||
|
|
||||||
|
### Связанный код
|
||||||
|
|
||||||
|
### Связанные документы
|
||||||
|
|
||||||
|
### История изменений
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
# API Method Rules
|
||||||
|
|
||||||
|
## Назначение
|
||||||
|
|
||||||
|
Этот файл задает правила для документов типа `api_method`.
|
||||||
|
|
||||||
|
## Когда использовать
|
||||||
|
|
||||||
|
Использовать для описания одного HTTP endpoint или одного отдельного API метода.
|
||||||
|
|
||||||
|
## Обязательная структура
|
||||||
|
|
||||||
|
Документ должен содержать:
|
||||||
|
- YAML frontmatter
|
||||||
|
- `# <title>`
|
||||||
|
- `## Summary`
|
||||||
|
- `## Details`
|
||||||
|
|
||||||
|
Внутри `## Details` обязательны:
|
||||||
|
- `### Описание`
|
||||||
|
- `### Сценарий`
|
||||||
|
- `### Функциональные требования`
|
||||||
|
- `### Нефункциональные требования`
|
||||||
|
- `### Контракт`
|
||||||
|
|
||||||
|
## Особые правила
|
||||||
|
|
||||||
|
- Сценарий оформляется как технический use case.
|
||||||
|
- Функциональные требования маркируются `FR-*`.
|
||||||
|
- Нефункциональные требования маркируются `NFR-*`.
|
||||||
|
- Контракт должен быть пригоден для последующей сборки OpenAPI.
|
||||||
|
- Если у метода есть интеграции, они выносятся в `### Интеграции`.
|
||||||
|
- Ошибки и HTTP-коды либо описываются в `### Ошибки`, либо ссылаются на централизованный каталог ошибок.
|
||||||
|
|
||||||
|
## Ошибки оформления
|
||||||
|
|
||||||
|
- Нельзя заменять контракт общим текстовым описанием.
|
||||||
|
- Нельзя смешивать несколько endpoint в одном документе.
|
||||||
|
- Нельзя хранить связи и навигацию вне frontmatter.
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
# Architecture Overview Rules
|
||||||
|
|
||||||
|
## Назначение
|
||||||
|
|
||||||
|
Этот файл задает правила для документов типа `architecture_overview`.
|
||||||
|
|
||||||
|
## Когда использовать
|
||||||
|
|
||||||
|
Использовать как входной документ для понимания системы, модуля или сервиса.
|
||||||
|
|
||||||
|
## Обязательная структура
|
||||||
|
|
||||||
|
Документ должен содержать:
|
||||||
|
- YAML frontmatter
|
||||||
|
- `# <title>`
|
||||||
|
- `## Summary`
|
||||||
|
- `## Details`
|
||||||
|
|
||||||
|
## Что описывать в Details
|
||||||
|
|
||||||
|
- границы системы
|
||||||
|
- основные компоненты
|
||||||
|
- ключевые взаимодействия
|
||||||
|
- интеграционные сценарии
|
||||||
|
- главные ограничения
|
||||||
|
- ссылки на дочерние документы по API, logic, domain и другим артефактам
|
||||||
|
|
||||||
|
## Ошибки оформления
|
||||||
|
|
||||||
|
- Нельзя дублировать в архитектурном обзоре полные API-контракты.
|
||||||
|
- Нельзя делать архитектурный обзор единственным документом на всю систему без декомпозиции.
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# Domain Entity Rules
|
||||||
|
|
||||||
|
## Назначение
|
||||||
|
|
||||||
|
Этот файл задает правила для документов типа `domain_entity`.
|
||||||
|
|
||||||
|
## Когда использовать
|
||||||
|
|
||||||
|
Использовать для описания одной доменной сущности, ее смысла, состояния и роли в системе.
|
||||||
|
|
||||||
|
## Обязательная структура
|
||||||
|
|
||||||
|
Документ должен содержать:
|
||||||
|
- YAML frontmatter
|
||||||
|
- `# <title>`
|
||||||
|
- `## Summary`
|
||||||
|
- `## Details`
|
||||||
|
|
||||||
|
## Что описывать в Details
|
||||||
|
|
||||||
|
- смысл сущности
|
||||||
|
- ключевые атрибуты
|
||||||
|
- состояния или инварианты
|
||||||
|
- использование сущности в системе
|
||||||
|
- интеграции с API, workflow или внешними потребителями, если они важны для понимания модели
|
||||||
|
|
||||||
|
## Ошибки оформления
|
||||||
|
|
||||||
|
- Нельзя смешивать несколько независимых сущностей в одном документе.
|
||||||
|
- Нельзя подменять доменную сущность описанием endpoint или workflow.
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
# Integration Doc Rules
|
||||||
|
|
||||||
|
## Назначение
|
||||||
|
|
||||||
|
Этот файл задает правила для документов типа `integration_doc`.
|
||||||
|
|
||||||
|
## Когда использовать
|
||||||
|
|
||||||
|
Использовать для описания интеграции между системами, сервисами или внешними провайдерами.
|
||||||
|
|
||||||
|
## Обязательная структура
|
||||||
|
|
||||||
|
Документ должен содержать:
|
||||||
|
- YAML frontmatter
|
||||||
|
- `# <title>`
|
||||||
|
- `## Summary`
|
||||||
|
- `## Details`
|
||||||
|
|
||||||
|
## Что описывать в Details
|
||||||
|
|
||||||
|
- цель интеграции
|
||||||
|
- участвующие стороны
|
||||||
|
- направление обмена
|
||||||
|
- ключевой сценарий взаимодействия
|
||||||
|
- ограничения и риски
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
# Logic Block Rules
|
||||||
|
|
||||||
|
## Назначение
|
||||||
|
|
||||||
|
Этот файл задает правила для документов типа `logic_block`.
|
||||||
|
|
||||||
|
## Когда использовать
|
||||||
|
|
||||||
|
Использовать для описания одного законченного блока логики, workflow или процесса.
|
||||||
|
|
||||||
|
## Обязательная структура
|
||||||
|
|
||||||
|
Документ должен содержать:
|
||||||
|
- YAML frontmatter
|
||||||
|
- `# <title>`
|
||||||
|
- `## Summary`
|
||||||
|
- `## Details`
|
||||||
|
|
||||||
|
## Что описывать в Details
|
||||||
|
|
||||||
|
- назначение логического блока
|
||||||
|
- входы и выходы
|
||||||
|
- последовательность выполнения
|
||||||
|
- интеграции
|
||||||
|
- ключевые ограничения
|
||||||
|
- состояние и ошибки, если они важны для понимания блока
|
||||||
|
|
||||||
|
## Ошибки оформления
|
||||||
|
|
||||||
|
- Нельзя описывать весь модуль целиком, если логика распадается на несколько независимых блоков.
|
||||||
|
- Нельзя превращать документ в пересказ исходного кода построчно.
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# UI Page Rules
|
||||||
|
|
||||||
|
## Назначение
|
||||||
|
|
||||||
|
Этот файл задает правила для документов типа `ui_page`.
|
||||||
|
|
||||||
|
## Когда использовать
|
||||||
|
|
||||||
|
Использовать для описания одной пользовательской страницы, экрана или отдельного UI-сценария.
|
||||||
|
|
||||||
|
## Обязательная структура
|
||||||
|
|
||||||
|
Документ должен содержать:
|
||||||
|
- YAML frontmatter
|
||||||
|
- `# <title>`
|
||||||
|
- `## Summary`
|
||||||
|
- `## Details`
|
||||||
|
|
||||||
|
## Что описывать в Details
|
||||||
|
|
||||||
|
- назначение страницы
|
||||||
|
- пользовательский сценарий
|
||||||
|
- основные блоки интерфейса
|
||||||
|
- связанные API и сущности
|
||||||
+33
-7
@@ -1,5 +1,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from app.core.agent.processes.v2.workflows.doc_update_from_feature.doc_rules_pipeline.models import DocRulesBundle
|
from app.core.agent.processes.v2.workflows.doc_update_from_feature.doc_rules_pipeline.models import DocRulesBundle
|
||||||
@@ -7,20 +8,45 @@ from app.core.agent.processes.v2.workflows.doc_update_from_feature.doc_rules_pip
|
|||||||
|
|
||||||
class DocRulesLoader:
|
class DocRulesLoader:
|
||||||
def __init__(self, root: Path | None = None) -> None:
|
def __init__(self, root: Path | None = None) -> None:
|
||||||
base = root or (Path(__file__).resolve().parents[3] / "doc_rules")
|
base_dir = Path(__file__).resolve().parents[3]
|
||||||
self._root = base
|
if root is not None:
|
||||||
|
self._root = root
|
||||||
|
return
|
||||||
|
profile = os.getenv("DOC_RULES_PROFILE", "legacy").strip().lower()
|
||||||
|
if profile == "legacy":
|
||||||
|
self._root = base_dir / "doc_rules"
|
||||||
|
return
|
||||||
|
self._root = base_dir / "doc_rules_v2"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def root(self) -> Path:
|
def root(self) -> Path:
|
||||||
return self._root
|
return self._root
|
||||||
|
|
||||||
def load(self) -> DocRulesBundle:
|
def load(self) -> DocRulesBundle:
|
||||||
|
bundle = self._load_from_root(self._root)
|
||||||
|
if bundle.supported_doc_types:
|
||||||
|
return bundle
|
||||||
|
# Safe fallback for quick rollback or incomplete v2 setup.
|
||||||
|
fallback = self._root.parent / "doc_rules"
|
||||||
|
if fallback != self._root:
|
||||||
|
fallback_bundle = self._load_from_root(fallback)
|
||||||
|
if fallback_bundle.supported_doc_types:
|
||||||
|
return fallback_bundle
|
||||||
|
return bundle
|
||||||
|
|
||||||
|
def _load_from_root(self, root: Path) -> DocRulesBundle:
|
||||||
|
artifact_rules = self._read_folder(root / "artifact-types", suffix=".md")
|
||||||
|
if not artifact_rules:
|
||||||
|
artifact_rules = self._read_folder(root / "types", suffix=".md")
|
||||||
|
sections = self._read_folder(root / "sections", suffix=".md")
|
||||||
|
if not sections:
|
||||||
|
sections = self._read_folder(root / "common-elements", suffix=".md")
|
||||||
return DocRulesBundle(
|
return DocRulesBundle(
|
||||||
documentation_rules=self._read_file(self._root / "documentation-rules.md"),
|
documentation_rules=self._read_file(root / "documentation-rules.md"),
|
||||||
global_rules=self._read_folder(self._root / "global", suffix=".md"),
|
global_rules=self._read_folder(root / "global", suffix=".md"),
|
||||||
artifact_rules=self._read_folder(self._root / "artifact-types", suffix=".md"),
|
artifact_rules=artifact_rules,
|
||||||
templates=self._read_templates(self._root / "templates"),
|
templates=self._read_templates(root / "templates"),
|
||||||
sections=self._read_folder(self._root / "sections", suffix=".md"),
|
sections=sections,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _read_templates(self, folder: Path) -> dict[str, str]:
|
def _read_templates(self, folder: Path) -> dict[str, str]:
|
||||||
|
|||||||
+7
-7
@@ -5,14 +5,14 @@ from app.core.agent.processes.v2.workflows.doc_update_from_feature.doc_rules_pip
|
|||||||
|
|
||||||
|
|
||||||
class DocRulesSelector:
|
class DocRulesSelector:
|
||||||
_DEFAULT_SECTIONS: tuple[str, ...] = ("summary", "details", "requirements-format")
|
_DEFAULT_SECTIONS: tuple[str, ...] = ("summary", "details", "tech-use-case", "fr", "requirements-format")
|
||||||
_SECTIONS_BY_TYPE: dict[str, tuple[str, ...]] = {
|
_SECTIONS_BY_TYPE: dict[str, tuple[str, ...]] = {
|
||||||
"api_method": ("summary", "details", "api-scenario", "api-contract", "requirements-format"),
|
"api_method": ("summary", "details", "tech-use-case", "fr", "api-contract", "requirements-format"),
|
||||||
"integration_doc": ("summary", "details", "api-contract", "requirements-format"),
|
"integration_doc": ("summary", "details", "tech-use-case", "fr", "api-contract", "requirements-format"),
|
||||||
"ui_page": ("summary", "details", "requirements-format"),
|
"ui_page": ("summary", "details", "tech-use-case", "fr", "requirements-format"),
|
||||||
"logic_block": ("summary", "details", "requirements-format"),
|
"logic_block": ("summary", "details", "tech-use-case", "fr", "requirements-format"),
|
||||||
"architecture_overview": ("summary", "details", "requirements-format"),
|
"architecture_overview": ("summary", "details", "tech-use-case", "fr", "requirements-format"),
|
||||||
"domain_entity": ("summary", "details", "requirements-format"),
|
"domain_entity": ("summary", "details", "tech-use-case", "fr", "requirements-format"),
|
||||||
}
|
}
|
||||||
|
|
||||||
def select(self, bundle: DocRulesBundle, doc_type: str) -> SelectedDocRules | None:
|
def select(self, bundle: DocRulesBundle, doc_type: str) -> SelectedDocRules | None:
|
||||||
|
|||||||
@@ -61,8 +61,8 @@ class IndexJobStore:
|
|||||||
cache_miss_files=row.cache_miss_files,
|
cache_miss_files=row.cache_miss_files,
|
||||||
error=payload,
|
error=payload,
|
||||||
)
|
)
|
||||||
stale_timeout_sec = max(1, int(os.getenv("RAG_RUNNING_STALE_TIMEOUT_SEC", "8")))
|
stale_timeout_sec = int(os.getenv("RAG_RUNNING_STALE_TIMEOUT_SEC", "0"))
|
||||||
if job.status == IndexJobStatus.RUNNING and self._is_stale(row.updated_at, stale_timeout_sec):
|
if stale_timeout_sec > 0 and job.status == IndexJobStatus.RUNNING and self._is_stale(row.updated_at, stale_timeout_sec):
|
||||||
payload = ErrorPayload(
|
payload = ErrorPayload(
|
||||||
code="index_stalled",
|
code="index_stalled",
|
||||||
desc="Indexing stalled in running state; likely blocked network call during embedding/auth.",
|
desc="Indexing stalled in running state; likely blocked network call during embedding/auth.",
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ class IndexingOrchestrator:
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
timeout_sec = max(1, int(os.getenv("RAG_INDEX_JOB_TIMEOUT_SEC", "15")))
|
timeout_sec = max(1, int(os.getenv("RAG_INDEX_JOB_TIMEOUT_SEC", "180")))
|
||||||
indexed, failed, cache_hits, cache_misses = await asyncio.wait_for(
|
indexed, failed, cache_hits, cache_misses = await asyncio.wait_for(
|
||||||
operation(progress_cb),
|
operation(progress_cb),
|
||||||
timeout=timeout_sec,
|
timeout=timeout_sec,
|
||||||
|
|||||||
@@ -217,11 +217,23 @@ class RagService:
|
|||||||
batch_size = max(1, int(os.getenv("RAG_EMBED_BATCH_SIZE", "16")))
|
batch_size = max(1, int(os.getenv("RAG_EMBED_BATCH_SIZE", "16")))
|
||||||
request_timeout_sec = max(1, int(os.getenv("RAG_EMBED_REQUEST_TIMEOUT_SEC", "5")))
|
request_timeout_sec = max(1, int(os.getenv("RAG_EMBED_REQUEST_TIMEOUT_SEC", "5")))
|
||||||
request_retries = max(1, int(os.getenv("RAG_EMBED_REQUEST_MAX_RETRIES", "1")))
|
request_retries = max(1, int(os.getenv("RAG_EMBED_REQUEST_MAX_RETRIES", "1")))
|
||||||
|
max_chars = max(200, int(os.getenv("RAG_EMBED_MAX_CHARS", "1200")))
|
||||||
|
overlap_chars = max(0, int(os.getenv("RAG_EMBED_OVERLAP_CHARS", "120")))
|
||||||
|
prepared = self._prepare_docs_for_embedding(docs, max_chars=max_chars, overlap_chars=overlap_chars)
|
||||||
|
if len(prepared) != len(docs):
|
||||||
|
LOGGER.warning(
|
||||||
|
"rag embed doc split: path=%s original_docs=%s prepared_docs=%s max_chars=%s overlap_chars=%s",
|
||||||
|
file.get("path", ""),
|
||||||
|
len(docs),
|
||||||
|
len(prepared),
|
||||||
|
max_chars,
|
||||||
|
overlap_chars,
|
||||||
|
)
|
||||||
metadata = self._document_metadata(file, repo_id, blob_sha)
|
metadata = self._document_metadata(file, repo_id, blob_sha)
|
||||||
for doc in docs:
|
for doc in prepared:
|
||||||
doc.metadata.update(metadata)
|
doc.metadata.update(metadata)
|
||||||
for start in range(0, len(docs), batch_size):
|
for start in range(0, len(prepared), batch_size):
|
||||||
batch = docs[start : start + batch_size]
|
batch = prepared[start : start + batch_size]
|
||||||
LOGGER.warning(
|
LOGGER.warning(
|
||||||
"rag embed batch start: path=%s batch_start=%s batch_size=%s timeout_sec=%s retries=%s",
|
"rag embed batch start: path=%s batch_start=%s batch_size=%s timeout_sec=%s retries=%s",
|
||||||
file.get("path", ""),
|
file.get("path", ""),
|
||||||
@@ -243,7 +255,67 @@ class RagService:
|
|||||||
)
|
)
|
||||||
for doc, vector in zip(batch, vectors):
|
for doc, vector in zip(batch, vectors):
|
||||||
doc.embedding = vector
|
doc.embedding = vector
|
||||||
return docs
|
return prepared
|
||||||
|
|
||||||
|
def _prepare_docs_for_embedding(
|
||||||
|
self,
|
||||||
|
docs: list[RagDocument],
|
||||||
|
*,
|
||||||
|
max_chars: int,
|
||||||
|
overlap_chars: int,
|
||||||
|
) -> list[RagDocument]:
|
||||||
|
prepared: list[RagDocument] = []
|
||||||
|
for doc in docs:
|
||||||
|
text = str(doc.text or "")
|
||||||
|
if len(text) <= max_chars:
|
||||||
|
prepared.append(doc)
|
||||||
|
continue
|
||||||
|
parts = self._split_text_for_embedding(text, max_chars=max_chars, overlap_chars=overlap_chars)
|
||||||
|
if len(parts) <= 1:
|
||||||
|
prepared.append(doc)
|
||||||
|
continue
|
||||||
|
for idx, part in enumerate(parts, start=1):
|
||||||
|
metadata = dict(doc.metadata)
|
||||||
|
metadata["embed_part_index"] = idx
|
||||||
|
metadata["embed_part_total"] = len(parts)
|
||||||
|
if doc.doc_id:
|
||||||
|
metadata["embed_original_doc_id"] = doc.doc_id
|
||||||
|
prepared.append(
|
||||||
|
RagDocument(
|
||||||
|
layer=doc.layer,
|
||||||
|
source=doc.source,
|
||||||
|
title=f"{doc.title} [part {idx}/{len(parts)}]",
|
||||||
|
text=part,
|
||||||
|
metadata=metadata,
|
||||||
|
links=list(doc.links),
|
||||||
|
span=doc.span,
|
||||||
|
doc_id=f"{doc.doc_id}:part:{idx}" if doc.doc_id else None,
|
||||||
|
lang=doc.lang,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return prepared
|
||||||
|
|
||||||
|
def _split_text_for_embedding(self, text: str, *, max_chars: int, overlap_chars: int) -> list[str]:
|
||||||
|
normalized = text.replace("\r\n", "\n").replace("\r", "\n")
|
||||||
|
parts: list[str] = []
|
||||||
|
start = 0
|
||||||
|
length = len(normalized)
|
||||||
|
while start < length:
|
||||||
|
hard_end = min(length, start + max_chars)
|
||||||
|
end = hard_end
|
||||||
|
if hard_end < length:
|
||||||
|
soft_start = min(length, start + max_chars // 2)
|
||||||
|
pivot = normalized.rfind("\n", soft_start, hard_end)
|
||||||
|
if pivot > start:
|
||||||
|
end = pivot + 1
|
||||||
|
chunk = normalized[start:end].strip()
|
||||||
|
if chunk:
|
||||||
|
parts.append(chunk)
|
||||||
|
if end >= length:
|
||||||
|
break
|
||||||
|
next_start = max(start + 1, end - overlap_chars)
|
||||||
|
start = next_start
|
||||||
|
return parts or [normalized]
|
||||||
|
|
||||||
def _with_file_metadata(self, docs: list[RagDocument], file: dict, repo_id: str, blob_sha: str) -> list[RagDocument]:
|
def _with_file_metadata(self, docs: list[RagDocument], file: dict, repo_id: str, blob_sha: str) -> list[RagDocument]:
|
||||||
metadata = self._document_metadata(file, repo_id, blob_sha)
|
metadata = self._document_metadata(file, repo_id, blob_sha)
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class GigaChatTokenProvider:
|
|||||||
def _fetch_token(self) -> tuple[str, float]:
|
def _fetch_token(self) -> tuple[str, float]:
|
||||||
if not self._settings.credentials:
|
if not self._settings.credentials:
|
||||||
raise GigaChatError("GIGACHAT_TOKEN is not set")
|
raise GigaChatError("GIGACHAT_TOKEN is not set")
|
||||||
timeout_sec = max(1, int(os.getenv("GIGACHAT_AUTH_TIMEOUT_SEC", "5")))
|
timeout_sec = max(1, int(os.getenv("GIGACHAT_AUTH_TIMEOUT_SEC", "20")))
|
||||||
headers = {
|
headers = {
|
||||||
"Content-Type": "application/x-www-form-urlencoded",
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
"Accept": "application/json",
|
"Accept": "application/json",
|
||||||
|
|||||||
Reference in New Issue
Block a user