spec: add requirement-writing profile to sdd-lab (WealthLedger/specs#66)

This commit is contained in:
2026-10-30 13:34:19 +03:00
parent d5a0e942a3
commit 4c13b1863f
7 changed files with 320 additions and 38 deletions
@@ -1,13 +1,16 @@
# Non-Functional Requirements
<!-- Только измеримые ограничения, которые меняют design или проверку. У каждой
строки есть порог и способ измерения. -->
строки есть согласованный порог с единицами, условия/нагрузка и способ измерения.
Для времени укажи точки начала/конца, для статистики — окно и агрегат.
Не превращай пример числа из исследования в утверждённую цель. -->
| ID | Категория | Требование | Порог | Измерение / evidence | Обоснование / источник |
| --- | --- | --- | --- | --- | --- |
| ID | Категория | Требование | Порог и единицы | Условия измерения | Измерение / evidence | Обоснование / источник |
| --- | --- | --- | --- | --- | --- | --- |
## Constraints Without Thresholds
<!-- Реальные, но пока неизмеримые ограничения: почему нет порога и кто его решит. -->
<!-- Реальные, но пока неизмеримые ограничения: почему нет порога, кто решит и какое
решение/проверку это блокирует. Не выдавай неизвестное за согласованный NFR. -->
## Open Questions
@@ -36,6 +36,8 @@
`changes requested` или `invalidated: <причина>`. Никогда не записывай решение,
которого владелец не давал. ПОСЛЕДНЯЯ строка gate — его состояние; более поздняя
rejected / changes requested / invalidated снимает этот gate и все последующие.
Для Specs: Validation отмечает нормоконтроль и смысловую проверку набора по
spec-writing.md; Findings — конкретные неясности/пропуски и их разрешение.
Пример:
| G1 | 2026-10-29 | proposal, change-profile | `openspec validate` OK; readiness: plan OK | product-analyst: 1 major — закрыт в Open Decisions | approved "ок, идём дальше" (сессия) |
| G2 | 2026-10-30 | specs | `openspec validate --strict` OK; readiness: plan OK | qa-engineer: в Scenario нет значения THEN | changes requested |
@@ -34,4 +34,6 @@
## Open Decisions
<!-- Ещё не принятые решения, способные изменить scope. Каждое: вопрос, кто решает,
что блокируется до ответа. Пусто, только если таких нет. -->
зависимое требование/артефакт и что блокируется до ответа. Несогласованное
правило, термин, порог или вариант поведения не заменяй допущением в Specs.
Пусто, только если таких вопросов нет. -->
@@ -10,19 +10,25 @@
## Coverage Matrix
<!-- Строка на каждый delta Requirement. Проверка — системный способ доказать его;
ids test cases, если выбран test-cases; либо «not verified: <риск-причина>».
<!-- Строка на каждый ADDED/MODIFIED/REMOVED Requirement. Назови покрытые Scenarios
точными headings и ветви таблицы/переходы, если они есть. Проверка даёт наблюдение,
отличающее исполнение нормы от нарушения; test cases — ссылками, не копиями.
Пропуск случая — «not verified: <риск-причина>» с названием случая.
Покрытие — только строки этой таблицы; упоминание требования в другом месте
файла покрытием не считается. REMOVED требует проверки миграции/регрессии.
При skip_specs: true вместо дельт укажи существующее поведение/ограничение,
которое сохраняем, точный источник и регрессионную проверку.
Пример:
| `portfolio/holdings` — `Итог портфеля не учитывает дубли операций` | повторный импорт того же файла брокера, итог не меняется | API | TC-HOLD-001 |
| `portfolio/holdings` — `Портфель показывает валюту` | not verified: только отображение, проверено ревью Scenario; риск низкий | — | — | -->
| `example-report` — `Отбор операций за календарный период` | Последний день периода и следующий день | Отчёт за октябрь включает X за 31.10 и исключает Y за 01.11 | API | ссылка на Scenario | -->
| Requirement | Проверка | Уровень | Test cases |
| --- | --- | --- | --- |
| Requirement / регрессионный baseline | Сценарии / ветви правила | Проверка / ожидаемое наблюдение | Уровень | Test cases |
| --- | --- | --- | --- | --- |
## Negative and Boundary Focus
<!-- Границы до/на/после порога, отказ, повтор, конкуренция, сохранность данных —
только применимое. Ссылайся на нормы, не придумывай исходы. -->
## Cross-system Verification
## Test Data and Environment Needs
@@ -34,3 +40,6 @@
## Regression Impact
## Gaps / Blockers
<!-- Цитата/heading → неоднозначность или непокрытый исход → владелец решения и
upstream-артефакт. Вопрос о значении expected result блокирует согласование. -->
@@ -1,5 +1,8 @@
<!--
Оставь только нужные этой дельте разделы; комментарий удали до approval.
Перед заполнением прочитай единый профиль:
openspec/schemas/wealth-ledger-sdd-lab/spec-writing.md.
Оставь только нужные этой дельте разделы; подсказки и образец не входят в результат.
Файл — specs/<capability-path>/spec.md с точным путём из Proposal.
Только новая capability: `## Purpose` в 1–2 предложения (от 50 символов).
Существующая capability: Purpose не добавляй.
@@ -11,22 +14,29 @@
- `## REMOVED Requirements` — heading Requirement плюс **Reason** и **Migration**.
- `## RENAMED Requirements` — только пары `FROM:` и `TO:`.
Каждый нормативный Requirement осознанно использует BCP 14 (RFC 2119 + RFC 8174)
uppercase SHALL/MUST и минимум один `#### Scenario:` с `- **WHEN**` и
`- **THEN**`. Строчные «must/should/may» — обычный язык.
Не оставляй пустые разделы операций и образцы.
Каркас ADDED/MODIFIED: устойчивое имя → субъект SHALL <наблюдаемый результат>
с явным условием, если оно нужно → определения/таблица → Scenarios.
SHALL NOT — запрет; существующие MUST/MUST NOT равнозначны. Один Requirement —
одно независимо принимаемое обязательство, не подсчёт предложений или SHALL.
Сценарий: GIVEN — существенное исходное состояние, WHEN — событие,
THEN — конкретный наблюдаемый исход. Минимум один Scenario; границы/отказы/повторы
добавляй по смыслу. Новое правило в одном лишь сценарии недопустимо.
Термины определены, величины имеют единицы и границы. Неизвестное — вопрос в
Open Decisions с владельцем и зависимым требованием, не придуманный ответ.
Пример:
Учебный образец формы, не продуктовая политика:
## ADDED Requirements
### Requirement: Итог портфеля не учитывает дубли операций
Система SHALL учитывать каждый идентификатор операции брокера в итоге портфеля
не более одного раза.
### Requirement: Отбор операций за календарный период
При формировании отчёта система SHALL включать все и только операции выбранного
счёта, дата учёта которых входит в выбранный период включительно по Europe/Moscow.
#### Scenario: Одна операция импортирована дважды
- **WHEN** операция `op-1` на 100.00 RUB импортирована дважды
- **THEN** итог портфеля увеличивается ровно на 100.00 RUB
#### 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 итог правильный» — нет ожидаемого значения; один Requirement на импорт,
отображение и экспорт сразу — раздели по поведению.
Плохо: «корректно отбирать операции до конца месяца» — не определены месяц,
границы, дата отбора и счёт; «THEN список корректен» — нет проверяемого исхода.
Для таблиц решений и переходов используй эталоны из профиля.
-->