Skip to content

Stores: планирование в собственном репозитории ​

Бета. Stores, references, working context и worksets — новые функции. Имена команд, флаги, форматы файлов и вывод JSON могут изменяться между выпусками. Все примеры ниже выполнялись на текущей сборке, но после обновления перечитайте это руководство.

Проблема, которую это решает ​

Обычно OpenSpec находится внутри одного репозитория с кодом: папка openspec/ рядом с вашим кодом, содержащая спецификации и изменения для этого репозитория.

Это перестаёт подходить, как только ваше планирование становится шире одного репозитория:

  • Ваша работа охватывает несколько репозиториев — одна фича затрагивает API-сервер, веб-приложение и общую библиотеку. В чьей папке openspec/ должен находиться план?
  • Ваша команда планирует до появления кода или планирует то, что никогда не станет кодом в этом репозитории.
  • Требования принадлежат одной команде, а используются другими. Версия в вики расходится, и ваш coding agent всё равно не может её прочитать.

Store — решение: отдельный репозиторий, единственная задача которого — планирование. Он имеет ту же структуру openspec/, которую вы уже знаете — спецификации и изменения — плюс небольшой файл идентификации. Вы регистрируете его на своей машине один раз, по имени, и затем любая обычная команда OpenSpec может работать в нём из любого места.

Структура ​

            team-plans  (хранилище: планирование в собственном репозитории)
            ├── .openspec-store/store.yaml     identity: "I am team-plans"
            └── openspec/
                ├── specs/      что является истинным
                └── changes/    что находится в работе
                      ▲
                      │ регистрируется на каждой машине по имени;
                      │ распространяется путём push/clone как обычный репозиторий
        ┌─────────────┼─────────────┐
        │             │             │
    web-app       api-server     mobile-app
   (code repo)   (code repo)    (code repo)

Два правила делают это простым:

  1. Хранилище — это просто git-репозиторий. Вы сами коммитите, пушите, пулите и ревьюите его. OpenSpec никогда не клонирует, не синхронизирует и не пушит ничего самостоятельно.
  2. Декларации, а не механизмы. Репозитории могут декларировать, как они связаны с хранилищами (показано ниже). Декларации изменяют то, что OpenSpec может вам сообщить — никогда не то, где ваши команды действуют.

Пять минут до первого хранилища ​

Две команды ведут вас от нуля до работающего изменения, привязанного к хранилищу:

bash
openspec store setup team-plans --path ~/openspec/team-plans
Store 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.
bash
openspec new change add-login --store team-plans
Using 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, вместо того чтобы рассыпать их по репозиториям кода.

Первый день (тот, кто настраивает):

bash
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) в начальном коммите. Каждое будущее клонирование рождается, зная, откуда оно пришло, поэтому проверки здоровья и сообщения об ошибках могут печатать полную, готовую к вставке инструкцию для коллег, у которых его ещё нет.

Каждый коллега (один раз на машину):

bash
git clone git@github.com:acme/team-plans.git ~/openspec/team-plans
openspec store register ~/openspec/team-plans

С этого момента все работают в одном репозитории планирования по имени:

bash
openspec status --store team-plans --change add-login
openspec show add-login --store team-plans

Обмен работой — это git, намеренно. Изменение, которое вы создаёте, существует только в вашем checkout, пока вы не закоммитите и не запушите его — как и код. Планы получают ветки, pull request'ы и ревью бесплатно, потому что хранилище — это обычный репозиторий.

Подключение репозиториев кода команды. Репозиторий кода, чьё планирование полностью вынесено наружу, нуждается ровно в одной строке в openspec/config.yaml:

yaml
# web-app/openspec/config.yaml
store: team-plans

Теперь каждая команда OpenSpec, запущенная внутри web-app, действует на team-plans без каких-либо флагов:

bash
cd ~/src/web-app
openspec status --change add-login
Using OpenSpec root: team-plans (/Users/you/openspec/team-plans)
...

Указатель — это запасной вариант, никогда не переопределение: явный --store всегда побеждает, и если репозиторий вырастит собственные папки планирования, они побеждают (с предупреждением удалить устаревший указатель).

Один дефолт для всех репозиториев на вашей машине. Если вы работаете с многими репозиториями кода, которые все планируют в одно хранилище, установите его один раз, глобально, вместо добавления строки store: в каждый репозиторий:

bash
openspec config set defaultStore team-plans

Теперь любая команда, запущенная вне корня планирования — и без --store и без указателя проекта — разрешается в team-plans. Она находится на дне списка приоритетов, поэтому --store, локальный корень и указатель store: проекта всё ещё побеждают. Баннер корня и блок JSON root сообщают source: "global_default" с id хранилища, поэтому вы всегда можете отличить машино-широкий дефолт от собственного указателя репозитория. Очистите его командой openspec config unset defaultStore. Если id не зарегистрировано, команды выдают ошибку и сообщают вам зарегистрировать его или очистить устаревший дефолт.

Пример: одна фича, два репозитория компонентов ​

Предположим, add-checkout-promo изменяет и checkout-api, и checkout-web. Команда хочет один общий продуктовый контракт, при этом каждый репозиторий кода всё ещё нуждается в собственных задачах реализации, ветке и ревью.

Используйте два уровня:

  1. Храните общее поведение в team-plans.
  2. Храните планы реализации в каждом репозитории компонента и ссылайтесь на хранилище как на контекст только для чтения.

Сначала спланируйте общий контракт в хранилище:

bash
openspec new change add-checkout-promo --store team-plans
openspec status --change add-checkout-promo --store team-plans

Предложение и спецификации должны описывать поведение на границе между компонентами — например, поля промоции, возвращаемые сервисом, и как фронтенд обрабатывает неподходящий checkout. Проведите ревью этого изменения в репозитории хранилища как любую другую ветку и pull request.

Какой контекст видит планирование? ​

Выбор хранилища изменяет корень OpenSpec; он не обнаруживает и не читает каждый репозиторий кода, который использует это хранилище. Инструкции хранилища видят артефакты и настроенный контекст в хранилище. Они видят код компонентов только когда эти папки также доступны агенту или редактору и агент их читает.

Workset — удобный способ открыть хранилище планирования и оба репозитория кода вместе:

bash
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 в настоящее время не направляет задачи в репозитории.

Когда каждому компоненту нужен независимо ограниченный цикл apply/review, дайте ему локальный корень OpenSpec и ссылайтесь на центральное хранилище, вместо того чтобы указывать на него:

yaml
# checkout-api/openspec/config.yaml (и аналогично в checkout-web)
schema: spec-driven
references:
  - team-plans

После того как общий контракт утверждён и доступен в основных спецификациях хранилища, создайте небольшой локальный change для части компонента:

bash
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 request'ов, чтобы ревьюеры могли видеть, какую версию контракта следует каждая реализация.

История: требования, пересекающие границы команд ​

Команда платформы владеет требованиями. Продуктовые команды строят на их основе, в своих репозиториях, со своими дизайнами. Ссылка описывает эту связь, не перемещая работу никого.

   platform-reqs (хранилище)                 api-server (code repo)
   владеет команда платформы                  владеет продуктовая команда
   ┌──────────────────────────┐          ┌──────────────────────────┐
   │ openspec/specs/          │ ◀────────│ openspec/config.yaml     │
   │   payments/spec.md       │ читает   │   references:            │
   │   auth/spec.md           │          │     - platform-reqs      │
   │                          │          │ openspec/specs/          │
   │ openspec/changes/        │          │   (их собственные дизайны)│
   │   работа платформы       │          │ openspec/changes/        │
   │                          │          │   (их собственная работа)│
   │                          │          └──────────────────────────┘
   └──────────────────────────┘

Продуктовая команда декларирует, на что она опирается в openspec/config.yaml своего репозитория:

yaml
references:
  - platform-reqs

Ссылки — это контекст только для чтения. Репозиторий сохраняет собственный корень openspec/; работа остаётся там. Что меняется: openspec instructions в этом репозитории теперь включает индекс спецификаций ссылаемого хранилища — каждая с однострочной сводкой и точной командой получения (openspec show <spec-id> --type spec --store platform-reqs). Агент, работающий в api-server, может найти верхнепотоковые требования к платежам, сослаться на них и написать свой низкоуровневый дизайн в собственном корне репозитория — без того, чтобы кто-либо копировал контекст вручную.

Ссылка может нести источник клонирования, чтобы коллеги, у которых хранилище ещё нет, получали полную инструкцию, а не тупик:

yaml
references:
  - { id: platform-reqs, remote: "git@github.com:acme/platform-reqs.git" }

Когда вы хотите открыть план и код вместе, создайте workset. Это личное и явное решение: каждый выбирает папки, с которыми он действительно работает на своей машине. Ничего из этих локальных путей checkout не коммитится в общий репозиторий планирования.

bash
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       все три открываются в вашем инструменте
bash
openspec workset create platform \
  --member ~/openspec/team-plans --member ~/src/api-server \
  --tool code
openspec workset list
platform  (открывается в 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>          вы указали явно                 → тот store
2. ближайший openspec/   реальный корень планирования    → этот репозиторий
   (поднимаясь из cwd)
3. store: pointer        config.yaml объявляет store     → тот store
4. defaultStore          глобальный конфиг задаёт        → тот store
                         машинный дефолт
5. ни один из выше       на этой машине зарегистрированы  → ошибка с
   перечисленных         store'ы?                          подсказкой выбора
                         нет зарегистрированных store'ов? → текущий каталог
                                                           (классическое поведение)

Строка Using OpenSpec root: (и блок root в выводе --json) сообщает, в каком случае вы находитесь.

Известные ограничения ​

  • Бета-форма. Всё на этой странице может меняться между релизами — имена, флаги, форматы файлов, ключи JSON.
  • Один checkout на store id на машину. Регистрация второго checkout под тем же id завершается ошибкой с подсказкой сначала выполнить store unregister.
  • Никогда не синхронизируется — так задумано. OpenSpec никогда не клонирует, не тянет и не пушит. Устаревший checkout показывает устаревшие спецификации, пока вы не выполните pull; ссылки индексируются на лету из того, что есть на диске.
  • Пустые папки планирования могут отсутствовать. Новый store может ещё не иметь openspec/changes/, openspec/specs/ или openspec/changes/archive/ в Git. Это допустимо в период беты; эти папки появятся, когда обычные команды создадут для них файлы.
  • Репозитории-указатели остаются указателями. Репозиторий только с конфигурацией, у которого в openspec/config.yaml объявлено store: <id>, рассматривается как внешний план, а не как локальный checkout store'а. Если вы намеренно хотите преобразовать такой репозиторий в локальный корень store'а, сначала удалите строку store:.
  • Некоторые команды остаются на месте. templates и устаревшие именные формы (openspec change show, ...) действуют только на текущий каталог — без --store. schemas следует каноническому порядку выбора корня и принимает --store <id>, сохраняя неизменной свою успешную структуру JSON-массива.
  • Состояние на машине существует только на этой машине. Реестр store'ов и workset'ы — локальные настройки. Никаких сведений о структуре вашей машины никогда не попадает в общий план.
  • Два способа запуска workset'ов. Инструмент, который не может быть запущен через файл рабочей области или флаги привязки к папкам, не может быть добавлен как opener.
  • В JSON агента есть известное расхождение в регистрации ключей (ключи семейства store — snake_case, семейства workflow — camelCase). Это описано в agent contract; унификация отложена до версионированного релиза.

Где что находится ​

ЧтоГдеОбщий?
План 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 reference (Stores, Doctor, Working context, Personal worksets) и agent contract.