diff --git a/openspec/schemas/wealth-ledger-sdd-lab/schema.yaml b/openspec/schemas/wealth-ledger-sdd-lab/schema.yaml index b632641..bf2c772 100644 --- a/openspec/schemas/wealth-ledger-sdd-lab/schema.yaml +++ b/openspec/schemas/wealth-ledger-sdd-lab/schema.yaml @@ -118,6 +118,13 @@ artifacts: Шаблоны: HTML-комментарии в шаблонах — подсказки для автора. В готовом артефакте их нет; удаляй до gate этого артефакта. + Качество требований: единый профиль для автора и reviewer — + `openspec/schemas/wealth-ledger-sdd-lab/spec-writing.md`. До утверждения Specs + автор проходит нормоконтроль и смысловую проверку набора из раздела Review; + назначенный по режиму reviewer перепроверяет их на существующем G2/G3. + Результат — в Validation и Findings Gate Log. Вопрос, меняющий норму или ожидаемый + результат, блокирует gate; предпочтение стиля само по себе не блокирует. + Change Profile (обязательная таблица, все 10 строк): - `yes` — только при конкретном trigger из instruction артефакта; в lab допустим `yes` с названной практикой («lab: практика data mapping»). @@ -196,6 +203,9 @@ artifacts: approved содержит дословную цитату и непустую Validation. - [ ] Specs: нет дублей `### Requirement:` в одном файле; MODIFIED/REMOVED/RENAMED FROM ссылаются на существующий canonical heading. + - [ ] Для предъявляемых на gate Specs пройдены оба прохода Review из + spec-writing.md: качество требований и полнота/согласованность итогового набора; + нет нерешённых вопросов о нормативном поведении. - [ ] test-cases: ids `TC-` уникальны, у каждого case есть Verifies в формате ссылки. - [ ] Каждый файл `analysis/contracts/` и `analysis/diagrams/` упомянут в `analysis/*.md`; JSON/YAML-контракты синтаксически валидны. @@ -220,10 +230,11 @@ artifacts: Independent Review (lab — на каждом gate; delivery — минимум G4): - G1: product-analyst ищет в проблеме и scope противоречия и скрытые решения. - - G2: qa-engineer — тестируемость; independent-reviewer — противоречия с canonical - specs и пропущенные error/boundary случаи. + - G2: qa-engineer — тестируемость; independent-reviewer — оба прохода Review из + spec-writing.md для delta и итогового набора с canonical specs. - G3: independent-reviewer — согласованность specs ↔ analysis ↔ design ↔ - qa-analysis ↔ tasks; security-reviewer, если выбран security-analysis. + qa-analysis ↔ tasks; без G2 также профиль Specs; security-reviewer, если выбран + security-analysis. - G4: independent-reviewer — код против утверждённых артефактов; qa-engineer — системная проверка по qa-analysis. - Reviewer не исправляет артефакт; findings идут по правилам обратной связи. @@ -262,15 +273,27 @@ artifacts: - G1 approved; используются только capabilities из Proposal. - Для существующей capability прочитай canonical spec целиком. - `skip_specs: true` — spec-файлы не создаются. + - Прочитай `openspec/schemas/wealth-ledger-sdd-lab/spec-writing.md`: это единый + профиль написания и ревью, включая эталоны, а не необязательные советы. Правила: - - Один Requirement = одно устойчивое observable behavior или инвариант. - - BCP 14 по политике `config.yaml`: uppercase SHALL/MUST — только для обязательств. - - У каждого Requirement ≥1 `#### Scenario:` с конкретными WHEN/THEN. + - Путь дельты — `specs//spec.md`, capability-path точно из Proposal. + - Один Requirement = одно независимо принимаемое наблюдаемое обязательство или + инвариант. Единый атомарный результат не дроби по числу SHALL. + - Новая норма: субъект + SHALL / SHALL NOT + результат с явным условием, если оно + нужно. MUST / MUST NOT равнозначны; BCP 14 — по политике `config.yaml`. + - Общая норма, нужные определения/таблицы, затем ≥1 `#### Scenario:` для + ADDED/MODIFIED: GIVEN по необходимости, конкретные WHEN/THEN. Scenario не + создаёт новую норму. Существующие headings и сохраняемые Scenarios не теряй. + - Термины бери из затронутых specs и предоставленного глоссария; новое определение + размещай внутри владеющего Requirement, а не только в исследовании или примере. - Бизнес-правила, инварианты (сохранение суммы, однократный учёт денег, знак и - точка округления) и граничные случаи — явные Requirements/Scenarios. + точка округления), единицы и существенные границы — явные нормы и Scenarios. + Для ветвлений/жизненного цикла используй таблицы по профилю, без дублирования + правил прозой. Неизвестные пороги и политики не выдумывай. - Допущение не оформляется как факт: неизвестное правило → вопрос в Open - Decisions Proposal, а не выдуманный Requirement. + Decisions Proposal с владельцем и зависимым требованием; зависимый gate ждёт + решения. Наблюдение в коде не подменяет согласованное намерение. - Не дели Requirements по repositories; имена систем/транспорт/endpoints — в system-analysis, если сама их identity не внешнее обязательство. @@ -291,7 +314,9 @@ artifacts: Обратная связь: намерение/scope/capabilities → Proposal; системы/контракты/ mappings → system-analysis; детали взаимодействия → ux-design. - Проверка: `openspec validate --strict --store wealth-ledger-specs`. + Проверка: `openspec validate --strict --store wealth-ledger-specs`, затем + оба прохода Review из spec-writing.md. Успех CLI не доказывает полноту смысла; + проверяй delta вместе с получающимся canonical набором. requires: - process-record @@ -445,8 +470,12 @@ artifacts: Правила: - Каждый NFR: id, порог, способ измерения, обоснование/источник. + - Для численного порога определи единицы, условия/нагрузку, точки начала и конца + измерения, окно или агрегат по необходимости. Контекст измерения нужен, + чтобы разные авторы и QA проверяли одно обязательство. - Нет порога — раздел Constraints Without Thresholds с владельцем решения; числа - не выдумывай. + не выдумывай. Если от порога зависит design или приёмка, вопрос блокирует + соответствующий gate до решения. - Security-NFR живут здесь; security-analysis ссылается на них по id. Не включай: механизмы достижения (design), семантику отказов (failure-model), @@ -572,10 +601,14 @@ artifacts: Назначение: Что проверить на уровне системы, чтобы доказать соответствие Specs и выбранным analysis-модулям, и с какой глубиной — по риску. + Прочитай `openspec/schemas/wealth-ledger-sdd-lab/spec-writing.md`: ожидаемый исход + берётся из нормы, а не из догадки QA или фактического поведения реализации. Глубина (условные разделы внутри обязательного артефакта): - - Всегда: Risk Assessment, Coverage Matrix (строка на каждый delta Requirement), - Gaps / Blockers. + - Всегда: Risk Assessment, Coverage Matrix (строка на каждый ADDED/MODIFIED/REMOVED + Requirement с указанием Scenarios/ветвей правила и способа проверки), Gaps / + Blockers. При `skip_specs: true` матрица фиксирует существующее поведение или + согласованное ограничение для регрессии и его источник, без выдуманных дельт. - Delivery standard: остальные разделы — только при наличии содержания; пустые удаляй, не пиши N/A. - Lab или complex: все разделы; Cross-system Verification обязателен при выбранных @@ -589,6 +622,9 @@ artifacts: неопределённый flow/ошибка/контракт → пробел в system-analysis. - Ссылайся на Scenarios, не переписывай их. Отдельные test cases — только через артефакт `test-cases`. + - По риску проверь существенные границы, строки таблиц, переходы, повторы, + конкуренцию и отсутствие запрещённых побочных эффектов. Пропуск проверки — + явное `not verified: <риск-причина>` для названного случая в матрице, не молчание. - Планы проверок отделены от результатов: результаты фиксируются на G4. - Automation: black-box кандидаты API/E2E; QA repo пока нет — `deferred until QA repo exists`. diff --git a/openspec/schemas/wealth-ledger-sdd-lab/spec-writing.md b/openspec/schemas/wealth-ledger-sdd-lab/spec-writing.md new file mode 100644 index 0000000..ccfbad5 --- /dev/null +++ b/openspec/schemas/wealth-ledger-sdd-lab/spec-writing.md @@ -0,0 +1,220 @@ +# 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 не нужна. diff --git a/openspec/schemas/wealth-ledger-sdd-lab/templates/nfr.md b/openspec/schemas/wealth-ledger-sdd-lab/templates/nfr.md index 6d37f60..6fafc56 100644 --- a/openspec/schemas/wealth-ledger-sdd-lab/templates/nfr.md +++ b/openspec/schemas/wealth-ledger-sdd-lab/templates/nfr.md @@ -1,13 +1,16 @@ # Non-Functional Requirements + строки есть согласованный порог с единицами, условия/нагрузка и способ измерения. + Для времени укажи точки начала/конца, для статистики — окно и агрегат. + Не превращай пример числа из исследования в утверждённую цель. --> -| ID | Категория | Требование | Порог | Измерение / evidence | Обоснование / источник | -| --- | --- | --- | --- | --- | --- | +| ID | Категория | Требование | Порог и единицы | Условия измерения | Измерение / evidence | Обоснование / источник | +| --- | --- | --- | --- | --- | --- | --- | ## Constraints Without Thresholds - + ## Open Questions diff --git a/openspec/schemas/wealth-ledger-sdd-lab/templates/process-record.md b/openspec/schemas/wealth-ledger-sdd-lab/templates/process-record.md index 138a5fb..7808107 100644 --- a/openspec/schemas/wealth-ledger-sdd-lab/templates/process-record.md +++ b/openspec/schemas/wealth-ledger-sdd-lab/templates/process-record.md @@ -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 | diff --git a/openspec/schemas/wealth-ledger-sdd-lab/templates/proposal.md b/openspec/schemas/wealth-ledger-sdd-lab/templates/proposal.md index 099715e..d45abe7 100644 --- a/openspec/schemas/wealth-ledger-sdd-lab/templates/proposal.md +++ b/openspec/schemas/wealth-ledger-sdd-lab/templates/proposal.md @@ -34,4 +34,6 @@ ## Open Decisions + зависимое требование/артефакт и что блокируется до ответа. Несогласованное + правило, термин, порог или вариант поведения не заменяй допущением в Specs. + Пусто, только если таких вопросов нет. --> diff --git a/openspec/schemas/wealth-ledger-sdd-lab/templates/qa-analysis.md b/openspec/schemas/wealth-ledger-sdd-lab/templates/qa-analysis.md index 32bf794..a7e472b 100644 --- a/openspec/schemas/wealth-ledger-sdd-lab/templates/qa-analysis.md +++ b/openspec/schemas/wealth-ledger-sdd-lab/templates/qa-analysis.md @@ -10,19 +10,25 @@ ## Coverage Matrix - + | `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 + + diff --git a/openspec/schemas/wealth-ledger-sdd-lab/templates/spec.md b/openspec/schemas/wealth-ledger-sdd-lab/templates/spec.md index ecaad36..c850685 100644 --- a/openspec/schemas/wealth-ledger-sdd-lab/templates/spec.md +++ b/openspec/schemas/wealth-ledger-sdd-lab/templates/spec.md @@ -1,5 +1,8 @@