221 lines
20 KiB
Markdown
221 lines
20 KiB
Markdown
# Spec Writing Profile
|
||
|
||
Профиль написания и ревью требований `wealth-ledger-sdd-lab`. Цель — одинаковое
|
||
понимание поведения разными авторами, разработчиками и QA, а не дословно одинаковые
|
||
документы. Это адаптация инженерных практик, не заявление о соответствии стандартам.
|
||
|
||
## Scope
|
||
|
||
Автор и reviewer читают профиль перед подготовкой или согласованием Specs. Правила
|
||
применяются к новым и изменяемым требованиям; весь canonical store ради стиля не
|
||
переписывается. Пути, delta-операции и gates задаёт `schema.yaml`.
|
||
|
||
Specs определяют наблюдаемое поведение. Обоснования и открытые решения — в Proposal,
|
||
межсистемные детали — в `analysis/`, механизмы — в design, способы доказательства —
|
||
в QA. Ни один downstream-артефакт не вводит новое поведение молча.
|
||
|
||
## Writing Rules
|
||
|
||
1. **Основание.** Каждое обязательство следует из согласованного намерения или
|
||
существующего контракта. Наблюдение в коде, гипотеза и пример — не решение
|
||
владельца. Неизвестное запиши в Open Decisions: вопрос, кто решает, зависимое
|
||
требование и что блокируется. Несогласованные числа и варианты не становятся нормой.
|
||
2. **Термины.** Используй названия из затронутых canonical specs и предоставленного
|
||
проектного глоссария. Один термин — одно значение в названном контексте. «Счёт»,
|
||
«брокерский счёт» и «учётная запись» не взаимозаменяемы. Новый или спорный термин
|
||
определи в теле владеющего им Requirement; остальные требования ссылаются на него.
|
||
Определение должно различать случаи, а не заменять слово синонимом. Общие термины
|
||
передаются в глоссарий через Docs Impact; новый файл словаря на каждый change не нужен.
|
||
3. **Атомарность.** Один Requirement — одно независимо принимаемое обязательство.
|
||
Если одну часть можно принять, а другую отклонить — раздели. Связанные условия,
|
||
сохранность данных при отказе и единый атомарный результат остаются вместе.
|
||
Число союзов или SHALL не определяет атомарность.
|
||
4. **Явная норма.** Назови субъект, условие применимости и наблюдаемый результат.
|
||
Для нового обязательства предпочитай SHALL / SHALL NOT; существующие MUST /
|
||
MUST NOT равнозначны и сохраняются. SHOULD / MAY не заменяют неопределённый исход:
|
||
допустимая вариативность и исключения должны быть согласованы и описаны.
|
||
«Корректно», «быстро», «при необходимости», «и/или», «и т. д.» без определения —
|
||
повод уточнить правило. Краткость не оправдывает потерю условий.
|
||
5. **Величины и границы.** Для расчёта задай входы, формулу, знак, валюту, точность
|
||
и момент округления, если они влияют на результат. Для периода — включительность
|
||
границ, дату/время учёта и часовой пояс; для порога — сравнение и точку отсчёта.
|
||
Различай ноль, отсутствие значения и неизвестный результат. Не добавляй допуск,
|
||
таймаут или округление без источника только ради измеримости.
|
||
6. **Свобода реализации.** Описывай «что», а не внутренние классы, библиотеки или
|
||
алгоритм. Если внутренний механизм можно заменить без изменения внешнего
|
||
обязательства, это design. Внешний формат или протокол допустим в Specs, когда
|
||
именно он является согласованным обязательством, а не удобством реализации.
|
||
|
||
## Requirement and Scenario
|
||
|
||
Порядок блока: `### Requirement:` с устойчивым именем → общая норма → нужные
|
||
определения/таблица → `#### Scenario:`. Для новых требований используй короткое имя
|
||
на русском; существующие headings сохраняй для native delta-сопоставления.
|
||
|
||
Выбирай форму по смыслу (адаптация EARS, не дополнительный синтаксис OpenSpec):
|
||
|
||
| Смысл | Каркас нормы |
|
||
| --- | --- |
|
||
| Постоянное свойство | Система SHALL … |
|
||
| Реакция на событие | При … система SHALL … |
|
||
| Зависимость от состояния | Пока … система SHALL … |
|
||
| Ошибка или исключение | Если … система SHALL … |
|
||
|
||
У ADDED/MODIFIED Requirement минимум один Scenario. GIVEN нужен, когда исходное
|
||
состояние влияет на результат; WHEN задаёт событие; THEN — наблюдаемый исход с
|
||
определённым ожидаемым значением или составом, не «работает правильно». AND уточняет
|
||
тот же исход. Шаги не описывают внутренние вызовы и селекторы UI.
|
||
|
||
Сначала общее правило, затем различающие примеры: основной путь, существенная
|
||
граница, иной исход, отказ, повтор или конкуренция — по применимости. Каждый сценарий
|
||
добавляет новый класс поведения. Не вводи правило только в Scenario и не переписывай
|
||
правило целиком для каждой комбинации данных. Сценарии показывают следствия нормы,
|
||
но несколько примеров не доказывают универсальный инвариант.
|
||
|
||
## Representation
|
||
|
||
| Когда прозы недостаточно | Представление и обязательные уточнения |
|
||
| --- | --- |
|
||
| Взаимодействуют несколько условий | Таблица решений: область входов, смысл «любое», политика совпадений (одна строка / первая / все), результат отсутствия совпадений или объяснение полноты |
|
||
| Результат зависит от истории | Переходы: исходное состояние, событие/условие, новое состояние, видимый эффект; существенные повторы и недопустимые переходы |
|
||
| Должно сохраняться свойство | Инвариант/формула с областью действия и единицами; примеры нуля, знака и округления по применимости |
|
||
|
||
Нормативная таблица находится внутри Requirement до первого Scenario и вводится
|
||
фразой с SHALL. Она — единственное определение правила, а не копия соседней прозы.
|
||
Неоднозначные пересечения строк — дефект, если явно не задан приоритет или сбор
|
||
результатов. Таблица безусловно не нужна каждому требованию. Внутренние состояния
|
||
реализации и межсистемные схемы остаются в analysis/design.
|
||
|
||
## Examples
|
||
|
||
Учебные примеры формы, не продуктовые решения WealthLedger. В реальном change
|
||
периоды, состояния и исходы берутся из его согласованных входов.
|
||
|
||
### Condition and Boundary
|
||
|
||
```markdown
|
||
## ADDED Requirements
|
||
|
||
### Requirement: Отбор операций за календарный период
|
||
При формировании отчёта система SHALL включать все и только операции выбранного
|
||
счёта, дата учёта которых входит в выбранный период включительно по Europe/Moscow.
|
||
|
||
#### Scenario: Последний день периода и следующий день
|
||
- **GIVEN** выбран период 01.10.2026–31.10.2026 и счёт A
|
||
- **AND** на счёте A есть операции X с датой учёта 31.10.2026 и Y с датой 01.11.2026
|
||
- **WHEN** формируется отчёт
|
||
- **THEN** отчёт включает X и не включает Y
|
||
```
|
||
|
||
Плохо: «Система SHALL корректно отбирать операции до конца месяца» — не определены
|
||
месяц, границы, дата отбора и счёт. «THEN список корректен» не позволяет проверить исход.
|
||
|
||
### Decision Table
|
||
|
||
```markdown
|
||
## ADDED Requirements
|
||
|
||
### Requirement: Различимость неполного и пустого итога
|
||
Система SHALL представлять итог расчёта по таблице. «Полнота» означает получение
|
||
всех данных выбранной выборки; «есть записи» — наличие хотя бы одной записи.
|
||
Оба условия логические. Совпадает ровно одна строка; «любое» означает оба значения.
|
||
Покрыты все комбинации.
|
||
|
||
| Полнота подтверждена | Есть записи | Видимый итог |
|
||
| --- | --- | --- |
|
||
| Нет | Любое | Недоступен, без числового итога |
|
||
| Да | Нет | Ноль и пояснение пустого результата |
|
||
| Да | Да | Рассчитанный итог |
|
||
|
||
#### Scenario: Известная часть не становится окончательной суммой
|
||
- **GIVEN** известна одна запись на 100 RUB, но полнота выборки не подтверждена
|
||
- **WHEN** пользователь просматривает результат
|
||
- **THEN** итог обозначен как недоступный, не показан ни как 100 RUB, ни как ноль
|
||
```
|
||
|
||
Плохо: строки «нет данных → 0» и «данные не полны → недоступно» без определения
|
||
«нет данных» — одному входу могут соответствовать два разных результата.
|
||
|
||
### State Transition
|
||
|
||
```markdown
|
||
## ADDED Requirements
|
||
|
||
### Requirement: Отмена формирования отчёта
|
||
При запросе отмены система SHALL изменять состояние формирования отчёта по таблице.
|
||
Область правила — состояния «Ожидает», «Отменён», «Готов»; начальное — «Ожидает».
|
||
Совпадает ровно одна строка. Таблица определяет только событие отмены.
|
||
|
||
| До | После | Результат отмены |
|
||
| --- | --- | --- |
|
||
| Ожидает | Отменён | Отмена подтверждена, отчёт не будет сформирован |
|
||
| Отменён | Отменён | Отмена подтверждена без повторного эффекта |
|
||
| Готов | Готов | Отмена отклонена, готовый отчёт сохранён |
|
||
|
||
#### Scenario: Повтор отмены
|
||
- **GIVEN** формирование отчёта уже отменено
|
||
- **WHEN** пользователь снова запрашивает отмену
|
||
- **THEN** отмена подтверждена, состояние остаётся «Отменён»
|
||
```
|
||
|
||
Плохо: «повтор ничего не делает» — не определён результат для пользователя.
|
||
|
||
## Review
|
||
|
||
Используй два прохода на существующем gate Specs (G2 или G3), не новый gate.
|
||
Автор выполняет самопроверку; назначенный по режиму reviewer перепроверяет независимо.
|
||
|
||
| Проход | Что проверить |
|
||
| --- | --- |
|
||
| Нормоконтроль | Native headings/операции; термины и единицы; явные субъект/условие/исход; атомарность; корректные ссылки; Scenario с проверяемым THEN |
|
||
| Смысл и набор | Необходимость и происхождение норм; основной путь, альтернативы, отказы и границы; повторы/конкуренция/сохранность по риску; непротиворечивость таблиц и итогового baseline; отсутствие выдуманных решений |
|
||
|
||
Проверь не только delta, но и получающийся набор вместе с canonical specs:
|
||
сохранились ли действующие ограничения, исключения, инварианты и сценарии? MODIFIED
|
||
заменяет полный блок; редакторское улучшение не разрешает удалить прежний сценарий
|
||
или незаметно переименовать Requirement.
|
||
|
||
Профиль не отменяет ограничений установленного CLI. При предупреждении о длине
|
||
сократи повторения или раздели действительно независимые обязательства; не убирай
|
||
условия и не прячь норму в комментарий/код ради успешного `--strict`.
|
||
|
||
Контрольный вопрос: «Назови существенную ошибочную реализацию и наблюдение, которым
|
||
это требование отличит её от соответствующей». Если ответ зависит от догадки,
|
||
укажи точную неопределённость. Это эвристика ревью, не доказательство полноты.
|
||
|
||
Finding: **файл/heading + цитата → нарушенное правило → два возможных толкования
|
||
или недостающий исход → вопрос владельцу/адресат исправления**. Reviewer возвращает
|
||
находки, не переписывает текст по вкусу. Пример: «до конца месяца» → неясна правая
|
||
граница → операция в последний день включается или исключается → уточнить в Specs.
|
||
Нерешённый вопрос, меняющий требование или ожидаемый результат, блокирует его gate;
|
||
косметическое предпочтение не блокирует. Validation и Findings — в существующем
|
||
Gate Log, без нового отчёта на каждый Requirement.
|
||
|
||
### Trial
|
||
|
||
Для проверки эффекта дай одним и тем же авторам/моделям одинаковые входы: простое
|
||
правило, ветвление, повтор/состояние и MODIFIED. До сравнения зафиксируй согласованные
|
||
исходы и намеренно оставленные неизвестные. Сравни ответы независимых читателей на
|
||
контрольные вопросы, пропуски и выдуманные нормы, время уточнения и ревью. Совпадение
|
||
формулировок и успешный CLI не считаются доказательством одинакового понимания.
|
||
|
||
## Sources and Adaptation
|
||
|
||
Из девяти исследований `sdd-spec-quality/*.md` и трёх сводок `result/*.pdf` выбраны
|
||
правила с понятной пользой для ручного Markdown-процесса. Первоисточники проверены
|
||
30.10.2026; критерии адаптированы, а не перенесены как обязательная сертификация.
|
||
|
||
| Источник | Что взято и где предел |
|
||
| --- | --- |
|
||
| [NASA SE Handbook, Appendix C, C.2–C.4](https://www.nasa.gov/reference/appendix-c-how-to-write-a-good-requirement/) | Необходимость, одна мысль, «что, а не как», проверяемость и согласованность; не сертификационный комплект документов |
|
||
| [INCOSE GtWR v4 Summary, с. 2–3](https://www.incose.org/wp-content/uploads/legacy/working-groups/requirements-wg/guidetowritingrequirements/incose_rwg_gtwr_v4_summary_sheet.pdf) | C1/C3/C5/C7 для отдельного требования, C10–C14 для набора; R4/R7/R33–R36 — термины, величины, время. Полный платный Guide не заявлен как проверенный |
|
||
| [EARS, автор методики](https://alistairmavin.com/ears/) | Каркасы условия/события/состояния/ошибки; русский язык — адаптация, не буквальная английская грамматика |
|
||
| [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119.html), [8174 §2](https://www.rfc-editor.org/rfc/rfc8174.html#section-2) | Значения uppercase SHALL/MUST и запретов; наличие ключевого слова само по себе не гарантирует качество |
|
||
| [Cucumber, Given/When/Then](https://cucumber.io/docs/gherkin/reference/) | Исходное состояние, событие, наблюдаемый исход; Markdown Scenario не становится исполняемым Gherkin-тестом |
|
||
|
||
Из предложений не приняты: жёсткие лимиты слов/сценариев, подсчёт SHALL вместо
|
||
атомарности, обязательные REQ-ID и скрытые атрибуты, JSON-first, новые линтеры и gates.
|
||
Из нормоконтроля конструкторской документации заимствовано разделение проверки формы
|
||
и смысла; соответствие ГОСТ, DO-178C или ISO/IEC/IEEE 29148 не заявляется. Таблицы и
|
||
инварианты используются по риску; обязательная формальная модель каждому change не нужна.
|