Stores: План у власному репозиторії
Beta. Stores, references, working context і worksets є новими. Назви команд, прапорці, формати файлів та вивід JSON можуть змінюватися між випусками. Кожен посібник нижче виконано на поточній збірці, але перечитайте цей посібник після оновлення.
Проблема, яку це вирішує
OpenSpec зазвичай знаходиться всередині одного репозиторію з кодом: папка openspec/ поруч із вашим кодом містить специфікації та зміни для цього репозиторію.
Це перестає підходити, коли ваше планування виходить за межі одного репозиторію:
- Ваша робота охоплює кілька репозиторіїв — одна функція зачіпає сервер API, веб-додаток і спільну бібліотеку. У чиїй папці
openspec/має знаходитися план? - Ваша команда планує до того, як з'явиться код, або планує речі, які ніколи не стануть кодом у цьому репозиторії.
- Вимогами володіє одна команда, а використовують інші. Вікі-версія відстає, а ваш агент кодування все одно не може її прочитати.
Store є відповіддю: окремий репозиторій, вся робота якого полягає в плануванні. Він має ту саму структуру openspec/, яку ви вже знаєте — специфікації та зміни — плюс невеликий файл ідентифікації. Ви реєструєте його на своїй машині один раз, за назвою, і потім кожна звичайна команда OpenSpec може працювати в ньому з будь-якого місця.
Структура
team-plans (сховище: планування у власному репозиторії)
├── .openspec-store/store.yaml ідентичність: "Я — team-plans"
└── openspec/
├── specs/ що є істинним
└── changes/ що знаходиться в русі
▲
│ зареєстровано на кожній машині за іменем;
│ поширюється через push/clone, як будь-який репозиторій
┌─────────────┼─────────────┐
│ │ │
web-app api-server mobile-app
(кодовий (кодовий (кодовий
репозиторій) репозиторій) репозиторій)Два правила роблять це простим:
- Сховище — це просто git-репозиторій. Ви самостійно комітите, пушите, пулите та рецензуєте його. OpenSpec ніколи не клонує, не синхронізує та не пушить нічого самостійно.
- Оголошення, а не механізми. Репозиторії можуть оголошувати, як вони пов'язані зі сховищами (показано нижче). Оголошення змінюють те, що OpenSpec може вам повідомити — ніколи не змінюють місце дії ваших команд.
П'ять хвилин до вашого першого сховища
Дві команди переведуть вас від нічого до робочої зміни, обмеженої сховищем:
openspec store setup team-plans --path ~/openspec/team-plansStore ready: team-plans
Location: /Users/you/openspec/team-plans
OpenSpec root: ready
Registry: registered
Next: run normal OpenSpec commands against this store, for example:
openspec new change <change-id> --store team-plans
Share this store by committing and pushing it like any Git repo.openspec new change add-login --store team-plansUsing OpenSpec root: team-plans (/Users/you/openspec/team-plans)
Created change 'add-login' at /Users/you/openspec/team-plans/openspec/changes/add-login/
Schema: spec-driven
Next: openspec status --change add-login --store team-plansОсь і вся модель. З цього моменту життєвий цикл точно такий, як ви знаєте — status, instructions, validate, archive — з --store team-plans на кожній команді, і кожне виведене підказка містить цей прапорець. Рядок Using OpenSpec root: завжди показує, де виконується команда.
Сценарій: одна команда, один планувальний репозиторій
Команда зберігає свої специфікації та зміни в team-plans, замість того щоб розкидати їх по кодових репозиторіях.
Перший день (той, хто налаштовує):
openspec store setup team-plans --path ~/openspec/team-plans \
--remote git@github.com:acme/team-plans.git
git -C ~/openspec/team-plans push -u origin mainПередача --remote записує URL для клонування у власний файл ідентифікації сховища (.openspec-store/store.yaml) під час початкового коміту. Кожен майбутній клон «знатиме», звідки він походить, тому перевірки здоров'я та повідомлення про помилки можуть вивести повне, готове до копіювання рішення для колег, які ще не мають цього сховища.
Кожен член команди (один раз на машину):
git clone git@github.com:acme/team-plans.git ~/openspec/team-plans
openspec store register ~/openspec/team-plansЗ цього моменту всі працюють в одному планувальному репозиторії за іменем:
openspec status --store team-plans --change add-login
openspec show add-login --store team-plansОбмін роботою — це git, навмисно. Зміна, яку ви створюєте, існує лише у вашому робочому каталозі, доки ви не закомітите й не запушите її — так само, як код. Плани отримують гілки, pull-запити та рецензування без додаткових зусиль, тому що сховище — це звичайний репозиторій.
Підключення кодових репозиторіїв команди. Кодовий репозиторій, планування якого повністю винесено назовні, потребує лише одного рядка у openspec/config.yaml:
# web-app/openspec/config.yaml
store: team-plansТепер кожна команда OpenSpec, запущена всередині web-app, діє на team-plans без жодних прапорців:
cd ~/src/web-app
openspec status --change add-loginUsing OpenSpec root: team-plans (/Users/you/openspec/team-plans)
...Вказівник є резервним варіантом, а не перевизначенням: явне --store завжди має перевагу, і якщо репозиторій виростить власні планувальні папки, вони матимуть перевагу (з попередженням про необхідність видалити застарілий вказівник).
Одне стандартне сховище для всіх репозиторіїв на вашій машині. Якщо ви працюєте з багатьма кодовими репозиторіями, які всі планують в одному сховищі, встановіть його один раз глобально, замість додавання рядка store: до кожного репозиторію:
openspec config set defaultStore team-plansТепер будь-яка команда, запущена поза планувальним коренем — і без --store та без проєктного вказівника — вирішує використовувати team-plans. Він знаходиться внизу списку пріоритетів, отже --store, локальний корінь і проєктний вказівник store: все ще мають перевагу. Банер кореня та блок JSON root повідомляють source: "global_default" з ідентифікатором сховища, тому ви завжди зможете відрізнити загальномашинне стандартне сховище від власного вказівника репозиторію. Очистіть його командою openspec config unset defaultStore. Якщо ідентифікатор не зареєстрований, команди повідомляють про помилку та пропонують зареєструвати його або очистити застаріле значення.
Приклад: одна функція, два компонентні репозиторії
Припустимо, add-checkout-promo змінює як checkout-api, так і checkout-web. Команда хоче один спільний контракт продукту, тоді як кожен кодовий репозиторій все ще потребує власних завдань реалізації, гілки та рецензування.
Використовуйте два рівні:
- Зберігайте спільну поведінку в
team-plans. - Зберігайте плани реалізації в кожному компонентному репозиторії та посилайтеся на сховище як на контекст лише для читання.
Спершу сплануйте спільний контракт у сховищі:
openspec new change add-checkout-promo --store team-plans
openspec status --change add-checkout-promo --store team-plansПропозиція та специфікації повинні описувати поведінку на межі компонентів — наприклад, поля акції, що повертаються сервісом, і як фронтенд обробляє непридатний для оформлення замовлення кошик. Рецензуйте цю зміну в репозиторії сховища, як будь-яку іншу гілку та pull-запит.
Який контекст бачить планувальник?
Вибір сховища змінює корінь OpenSpec; він не виявляє та не читає всі кодові репозиторії, які використовують це сховище. Інструкції сховища бачать артефакти та налаштований контекст у сховищі. Код компонентів вони бачать лише тоді, коли ці папки також доступні агенту чи редактору, і агент їх читає.
Робочий набір (workset) — це зручний спосіб відкрити планувальне сховище та обидва кодові репозиторії разом:
openspec workset create checkout-promo \
--member ~/openspec/team-plans \
--member ~/src/checkout-api \
--member ~/src/checkout-web \
--tool code
openspec workset open checkout-promoЦе робить папки видимими в одному робочому просторі IDE. Це не копіює вихідний контекст до сховища, не вибирає зачеплені репозиторії та не надає агенту дозволу на їх редагування. Розміщуйте стійкі міжкомпонентні факти в спільних специфікаціях; не покладайтеся на те, що планувальник пам'ятатиме код, який він випадково переглянув.
Як починається реалізація в кожному репозиторії?
Коли не застосовується явний --store або ближчий корінь openspec/, вказівник store: team-plans направляє команди до цього сховища. Це не розбиває список завдань сховища за каталогом, з якого було викликано apply. Наразі OpenSpec не маршрутизує завдання до репозиторіїв.
Коли кожен компонент потребує незалежно обмеженого циклу застосування/рецензування, надайте йому локальний корінь OpenSpec і посилайтеся на центральне сховище, а не вказуйте на нього:
# checkout-api/openspec/config.yaml (і так само в checkout-web)
schema: spec-driven
references:
- team-plansПісля того як спільний контракт затверджено та він доступний в основних специфікаціях сховища, створіть невелику локальну зміну для частини компонента:
cd ~/src/checkout-api
openspec new change implement-checkout-promo-api
cd ~/src/checkout-web
openspec new change implement-checkout-promo-uiІндекс посилань в інструкціях кожного репозиторію надає резюме специфікації сховища та точну команду отримання openspec show ... --store team-plans. Кожна локальна пропозиція посилається на цей спільний контракт, а її завдання описують лише роботу в цьому компоненті. Потім запустіть /opsx:apply в кожному репозиторії окремо; визначення кореня гарантує, що артефакти та реалізаційні зміни обмежені цим репозиторієм. Тепер зміни в сервісі та фронтенді можна тестувати, рецензувати, зливати та архівувати незалежно.
Якщо реалізація повинна початися, поки зміна в спільному сховищі ще активна, отримайте її явно командою openspec show add-checkout-promo --store team-plans; індекси посилань перелічують канонічні специфікації сховища, а не активні зміни сховища. Підтримуйте зв'язок між гілкою сховища та компонентними гілками в описах pull-запитів, щоб рецензенти могли бачити, яку версію контракту використовує кожна реалізація.
Сценарій: вимоги, що перетинають межі команд
Платформна команда володіє вимогами. Продуктові команди розробляють на їх основі, у своїх власних репозиторіях, зі своїми дизайнами. Посилання описує цей зв'язок, не переміщуючи чиюсь роботу.
platform-reqs (сховище) api-server (кодовий репозиторій)
належить платформній команді належить продуктовій команді
┌──────────────────────────┐ ┌──────────────────────────┐
│ openspec/specs/ │ ◀────────│ openspec/config.yaml │
│ payments/spec.md │ читає │ references: │
│ auth/spec.md │ │ - platform-reqs │
│ │ │ openspec/specs/ │
│ openspec/changes/ │ │ (їх власні дизайни) │
│ робота платформи │ │ openspec/changes/ │
│ │ │ (їх власна робота) │
│ │ └──────────────────────────┘
└──────────────────────────┘Продуктова команда оголошує, на що вона спирається у файлі openspec/config.yaml свого репозиторію:
references:
- platform-reqsПосилання є контекстом лише для читання. Репозиторій зберігає власний корінь openspec/; робота залишається там. Що змінюється: openspec instructions у цьому репозиторії тепер містить індекс специфікацій посилального сховища — кожна з однорядковим резюме та точною командою отримання (openspec show <spec-id> --type spec --store platform-reqs). Агент, що працює в api-server, може знайти вищі вимоги до платежів, процитувати їх і написати свій низькорівневий дизайн у власному корені репозиторію — без необхідності комусь копіювати контекст навколо.
Посилання може містити джерело для клонування, тож колеги, які ще не мають сховища, отримують повне рішення замість глухого кута:
references:
- { id: platform-reqs, remote: "git@github.com:acme/platform-reqs.git" }Коли ви хочете відкрити план і код разом, створіть робочий набір (workset). Це особисте та явне: кожен обирає папки, з якими він фактично працює на своїй машині. Нічого щодо цих локальних шляхів робочих копій не комітиться до спільного планувального репозиторію.
openspec workset create platform \
--member ~/openspec/platform-reqs \
--member ~/src/api-server \
--member ~/src/web-appДва питання, які ви завжди можете поставити
"Чи здорове моє налаштування?" — openspec doctor перевіряє поточний корінь та його посилальні сховища, лише для читання, з готовим до копіювання рішенням для кожної знахідки:
Doctor
Root
Location: /Users/you/src/api-server
OpenSpec root: ok
References
- platform-reqs: ok (/Users/you/openspec/platform-reqs)
- design-system: Referenced store 'design-system' is not registered on this machine.
Fix: git clone -- git@github.com:acme/design-system.git '/Users/you/openspec/design-system' && openspec store register '/Users/you/openspec/design-system' --id design-system"З чим я працюю?" — openspec context збирає робочий набір з оголошень OpenSpec: корінь та сховища, на які він посилається.
Working context for api-server (/Users/you/src/api-server)
OpenSpec root
api-server /Users/you/src/api-server
Referenced stores
platform-reqs /Users/you/openspec/platform-reqs
Fetch: openspec show <spec-id> --type spec --store platform-reqsОбидві підтримують --json для агентів. openspec context --code-workspace <path> додатково записує файл робочого простору VS Code, що містить весь набір — єдиний запис, який виконує ця команда.
Worksets: знову відкрийте папки, з якими ви працюєте разом
Окремо від усього вищезазначеного: більшість людей щосесії відкривають одні й ті самі кілька папок разом — репозиторій планування та два-три репозиторії коду. Workset — це особистий, іменований вигляд саме цього набору, який відкривається однією командою у вашому обраному інструменті.
workset "platform" openspec workset open platform
├── team-plans ~/openspec/team-plans │
├── api-server ~/src/api-server ▼
└── web-app ~/src/web-app all three open in your toolopenspec workset create platform \
--member ~/openspec/team-plans --member ~/src/api-server \
--tool code
openspec workset listplatform (opens in VS Code)
team-plans /Users/you/openspec/team-plans
api-server /Users/you/src/api-serverКоманда openspec workset open platform запускає збережений інструмент: редактори (VS Code, Cursor) відкривають одне вікно з усіма учасниками та повертаються. Перший учасник є основним. Інструмент можна замінити будь-коли за допомогою --tool <id>.
Worksets навмисно не є спільним станом. Вони зберігаються на вашому комп'ютері, ніколи не комітяться та не роблять жодних тверджень про роботу — вони лише фіксуют, що ви любите відкривати разом. Видалення workset ніколи не торкається папок-учасників. Нові інструменти — це конфігурація, а не код: будь-який інструмент, який запускається через файл робочого простору або прапорці прикріплення папок, можна додати під ключем openers у глобальній конфігурації (openspec config edit).
Як команди визначають, де діяти
Кожна звичайна команда визначає свій корінь однаковим чином, у такому порядку:
1. --store <id> you said so explicitly → that store
2. nearest openspec/ a real planning root here → this repo
(walking up from cwd)
3. store: pointer config.yaml declares a store → that store
4. defaultStore global config sets a machine → that store
default
5. none of the above stores registered on this → error with a
machine? selection hint
no stores registered? → the current
directory
(classic behavior)Рядок Using OpenSpec root: (та блок root у виведенні --json) повідомляє вам, який випадок у вас.
Відомі обмеження
- Бета-форма. Усе на цій сторінці може змінюватися між випусками — назви, прапорці, формати файлів, ключі JSON.
- Одна копія на store id на машину. Реєстрація другої копії під тим самим id завершується помилкою з підказкою спочатку виконати
store unregister. - Жодного синхронізаційного механізму — за проєктом. OpenSpec ніколи не клонує, не отримує та не надсилає. Застаріла копія показує застарілі специфікації, доки ви не отримаєте оновлення; посилання індексуються наживо з того, що є на диску.
- Порожні папки планування можуть бути відсутніми. У новому store може ще не бути
openspec/changes/,openspec/specs/абоopenspec/changes/archive/у Git. Це приймається під час бета-версії; ці папки з'являються, коли звичайні команди створюють файли для них. - Репозиторії-вказівники залишаються вказівниками. Репозиторій лише з конфігурацією, у якого
openspec/config.yamlоголошуєstore: <id>, вважається зовнішнім плануванням, а не копією store для реєстрації. Спочатку видаліть рядокstore:, якщо ви навмисно хочете перетворити цей репозиторій на локальний корінь store. - Деякі команди залишаються на своїх місцях.
templatesта застарілі іменникові форми (openspec change show, ...) діють лише на поточну директорію — без--store.schemasдотримується канонічного пріоритету вибору кореня та приймає--store <id>, зберігаючи незмінною свою успішну структуру масиву JSON. - Стан на кожну машину — це стан на кожну машину. Реєстр store та worksets — це локальні налаштування. Нічого про розташування вашої машини ніколи не комітиться у спільне планування.
- Два стиліR запуску для worksets. Інструмент, який не можна запустити через файл робочого простору або прапорці прикріплення папок, не може бути доданий як відкривач.
- У Agent JSON є відома розбіжність регістру (ключі сімейства store — snake_case, сімейство workflow — camelCase). Документовано у контракті агента; уніфікація відкладена до версіонованого випуску.
Де що зберігається
| Що | Де | Спільне? |
|---|---|---|
| Планування store | <store>/openspec/ (специфікації, зміни) | Так — комітьте та надсилайте |
| Ідентичність store | <store>/.openspec-store/store.yaml | Так — комітиться разом із store |
| Реєстр store | <data dir>/openspec/stores/registry.yaml | Ні — лише ця машина |
| Worksets | <data dir>/openspec/worksets/ | Ні — лише ця машина |
<data dir> — це ~/.local/share/openspec на macOS та Linux (або $XDG_DATA_HOME/openspec, якщо встановлено), та %LOCALAPPDATA%\openspec на Windows.
Довідка
Точні прапорці та структури JSON для кожної команди на цій сторінці: довідка CLI (Stores, Doctor, Working context, Personal worksets) та контракт агента.