Skip to content

Написання якісних специфікацій ​

Ви рідко пишете специфікацію з чистого аркуша. Ви описуєте зміну простими словами, /opsx:propose складає вимоги та сценарії, а потім ви робите їх якісними. Ця сторінка присвячена саме цьому останньому етапу — що таке «якісно» і як спрямувати ШІ до цього.

Це доповнення до Відгуку на зміну: відгук — це виявлення слабких місць у чернетці, а написання — це знання, з чого складається сильна специфікація.

Специфікація — це поведінка, а не код ​

Специфікація описує, що ваша система робить, у термінах, які може перевірити будь-хто, — а не як вона реалізована. Вона складається з вимог (висловлювань про поведінку) та сценаріїв (конкретних прикладів, які їх доводять).

markdown
### Requirement: Session Timeout
The system SHALL expire a session after 30 minutes of inactivity.

#### Scenario: Idle timeout
- GIVEN an authenticated session
- WHEN 30 minutes pass with no activity
- THEN the session is invalidated and the user must re-authenticate

Залишайте як — чергу, бібліотеку, схему таблиці — у design.md або в коді. Коли поведінка та реалізація змішуються в одній вимозі, вимога перестає бути тестованою і починає застарівати щойно код змінюється.

Що робить вимогу якісною ​

Якісна вимога — це одна поведінка, сформульована настільки просто, що її можна передати комусь іншому для перевірки.

  • Одне твердження, одне SHALL/MUST. Якщо в вимозі три застереження «і також», це насправді три вимоги. Розділіть їх.

  • Спостережна. Хтось поза кодом повинен мати змогу визначити, чи виконується вона. «Система SHALL показувати банер помилки, коли завантаження перевищує 10 МБ» — спостережно. «Система SHALL коректно обробляти великі завантаження» — ні.

  • Відповідна сила. OpenSpec використовує ключові слова RFC 2119, і вони означають різне:

    Ключове словоЗначення
    MUST / SHALLЖорстка вимога. Без компромісів.
    SHOULDСильна рекомендація з можливістю обґрунтованого винятку.
    MAYСправді необов'язково.

    За замовчуванням використовуйте MUST/SHALL. Застосовуйте SHOULD лише тоді, коли ви справді маєте на увазі «якщо немає вагомих причин інакше».

Тест для вимоги: чи міг би тестувальник, який ніколи не бачив коду, визначити, чи вона виконана? Якщо ні — її потрібно уточнити.

Що робить сценарій якісним ​

Сценарії — це місце, де вимога доводить свою цінність. Кожен із них — це конкретний GIVEN / WHEN / THEN, який може стати автоматизованим тестом.

  • Він перевіряє свою вимогу. Сценарій, який просто перефразує вимогу іншими словами, нічого не перевіряє. Зробіть його конкретною ситуацією з конкретним результатом.
  • Покривайте важливі випадки, а не лише успішний шлях. Коректний вхід — це легко. Порожній ввід, прострочений токен, друге натискання, те, що йде не так, — саме там живуть баги, і саме там сценарій найцінніший.
  • Назвіть випадок у заголовку. «Scenario: Rejects an expired token» одразу показує рецензенту, що покрито; «Scenario: Test 2» — ні.

Корисна звичка: перед затвердженням запитайте себе який один випадок мене розчарує, якщо він зламається? — і переконайтеся, що сценарій його називає.

Обирайте правильний тип дельти ​

Зміна описує свої редагування специфікацій трьома типами розділів. Використання правильного з них зберігає чесність ваших заархівованих специфікацій:

  • ## ADDED Requirements — зовсім нова поведінка, яка раніше не існувала.
  • ## MODIFIED Requirements — поведінка, яка вже існувала і змінюється. Включіть повну нову версію; коротка примітка про зміни допоможе рецензенту.
  • ## REMOVED Requirements — поведінка, яка прибирається, з рядком про причину.

Під час архівування ADDED додається до основної специфікації, MODIFIED замінює стару версію, а REMOVED видаляється з неї. Видаліть останню вимогу можливості — і вона виводиться з експлуатації: замість того, щоб залишати специфікацію без вмісту, архів видаляє openspec/specs/<capability>/spec.md. Оскільки це єдиний крок архівування, який видаляє файл, його потрібно явно запросити — додайте retire_capabilities: true до .openspec.yaml зміни, поряд із schema:, який цей файл уже потребує. Без цього архівування переривається і повідомляє про це. Виведення з експлуатації видаляє весь файл, тому воно також відхиляється, поки специфікація містить щось поза заголовком, ## Purpose та блоками вимог — розділ ## Notes, коментар під вимогою. Переривання називає ці рядки; перемістіть їх у ## Purpose або в вимогу, або видаліть специфікацію вручну. Для специфікації в робочому каталозі викликача вивід архівування також називає git checkout, який відновлює закомічений файл; обрані сховища отримують рекомендації щодо відновлення в межах checkout замість цього. Якщо ви позначите реальну зміну як ADDED, ви отримаєте дві суперечливі вимоги; якщо ви опишете нову поведінку як MODIFIED, не буде нічого для заміни. Якщо сумніваєтесь, відкрийте поточну специфікацію та перевірте, чи вимога вже там є.

Є ще один розділ, який варто знати. Коли ваша дельта створює можливість, яка ще не існує, почніть її з ## Purpose — одне-два речення про те, для чого ця можливість. Архів використовує його як Purpose основної специфікації, яку він створює; пропустіть його — і отримаєте заповнювач TBD, який потрібно заповнити вручну. Існуюча специфікація вже має Purpose, тому Purpose дельти там ігнорується — редагуйте openspec/specs/<capability-path>/spec.md напряму, щоб його змінити. Тут <capability-path> — це каталог відносно specs/, наприклад user-auth у плоскому проєкті або identity/user-auth у проєкті, організованому за доменами.

Дотримуйтесь відповідного розміру зміни ​

Найпоширеніша помилка автора — це не погано сформульована вимога, а зміна, яка намагається бути трьома змінами.

Якісна зміна має одне намір, який можна висловити одним реченням. «Додати перемикач темного режиму.» «Обмежити частоту запитів до кінцевої точки входу.» «Мігрувати сесії з cookie.» Якщо для опису зміни потрібно багато «і також», це сигнал розділити її.

Прикмети того, що зміна завелика:

  • Обсяг пропозиції читається як список незалежних функцій.
  • Відгук займе півдня, тому ніхто цього не зробить.
  • Двоє людей не могли б працювати над нею без зіткнень.
  • Половина завдань могла б бути випущена окремо.

Менші зміни легше рецензувати, легше реалізувати за одну зосереджену сесію та легше аналізувати через пів року, коли архів — це все, що залишилось. Ви завжди можете запускати кілька змін паралельно — дивіться Редагування та ітерації та Робочі процеси.

Також трапляється протилежне: виправлення однієї літери не потребує трьох вимог і документації проєкту. Дотримуйтесь відповідного рівня формальності.

Як спрямувати ШІ до якісної чернетки ​

Оскільки /opsx:propose робить першу чернетку, якість того, що ви отримуєте, залежить від якості того, що ви йому даєте. Вам не потрібно писати вимоги вручну — вам потрібно правильно спрямувати ШІ:

  • Сформулюйте намір і межі. «Додати перемикач темного режиму, який при першому завантаженні бере налаштування ОС — не чіпати існуючий API теми.» Частина поза межами не менш важлива, ніж частина в межах.
  • Назвіть випадки, які вас цікавлять. «Переконайтеся, що є сценарій для користувача, який уже вручну обрав тему.» ШІ покриває те, на що ви вказуєте.
  • Потім редагуйте. Це звичайний Markdown. Уточніть розмиту SHALL, видаліть сценарій, який нічого не перевіряє, додайте випадок, який він пропустив, — або попросіть ШІ: «вимога щодо таймауту розмита, закріпіть її на 30 хвилин.»

Чернетка, уточнення, повторення. Кілька раундів цього дають специфікацію, якій можна довіряти, — і саме в цьому сенс.

Швидкий чек-лист ​

Куди йти далі ​