Skip to content

Składy: Planowanie w osobnym repozytorium ​

Beta. Składy, referencje, kontekst roboczy i zestawy robocze to nowe funkcje. Nazwy poleceń, flagi, formaty plików i wyjście JSON mogą jeszcze zmieniać się między wersjami. Każda instrukcja poniżej została wykonana na bieżącej wersji, ale po aktualizacji warto ponownie przeczytać ten przewodnik.

Problem, który to rozwiązuje ​

OpenSpec normalnie mieszka w jednym repozytorium kodu: folder openspec/ obok Twojego kodu, zawierający specyfikacje i zmiany dla tego repozytorium.

To przestaje wystarczać, gdy planowanie wykracza poza jedno repozytorium:

  • Twoja praca obejmuje kilka repozytoriów — jedna funkcja dotyka serwera API, aplikacji webowej i wspólnej biblioteki. W czyim folderze openspec/ ma mieszkać plan?
  • Twój zespół planuje, zanim kod jeszcze istnieje, albo planuje rzeczy, które nigdy nie staną się kodem w tym repozytorium.
  • Wymagania są własnością jednego zespołu, a konsumowane przez inne. Wersja na wiki się rozjeżdża, a Twój agent kodujący i tak nie potrafi jej odczytać.

Skład to odpowiedź: samodzielne repozytorium, którego jedynym zadaniem jest planowanie. Ma ten sam kształt openspec/, który już znasz — specyfikacje i zmiany — plus mały plik tożsamości. Rejestrujesz go na swojej maszynie raz, pod nazwą, a następnie każde zwykłe polecenie OpenSpec może w nim działać z dowolnego miejsca.

Kształt ​

            team-plans  (magazyn: planowanie w swoim własnym repozytorium)
            ├── .openspec-store/store.yaml     tożsamość: "Jestem team-plans"
            └── openspec/
                ├── specs/      co jest prawdą
                └── changes/    co jest w ruchu
                      ▲
                      │ zarejestrowany na każdej maszynie po nazwie;
                      │ współdzielony przez push/clone jak każde repozytorium
        ┌─────────────┼─────────────┐
        │             │             │
    web-app       api-server     mobile-app
   (repo kodu)   (repo kodu)    (repo kodu)

Dwie zasady utrzymują prostotę:

  1. Magazyn to po prostu repozytorium git. Samodzielnie commitujesz, pushujesz, pullujesz i przeglądasz. OpenSpec nigdy nie klonuje, nie synchronizuje ani nie wypycha niczego samodzielnie.
  2. Deklaracje, a nie mechanizmy. Repozytoria mogą deklarować, jak odnoszą się do magazynów (pokazane poniżej). Deklaracje zmieniają to, co OpenSpec może ci powiedzieć – nigdy nie miejsce, gdzie działają twoje polecenia.

Pięć minut do pierwszego magazynu ​

Dwa polecenia przenoszą cię od zera do działającej zmiany w zakresie magazynu:

bash
openspec store setup team-plans --path ~/openspec/team-plans
Magazyn gotowy: team-plans
Lokalizacja: /Users/you/openspec/team-plans
Korzeń OpenSpec: gotowy
Rejestr: zarejestrowany

Dalej: uruchamiaj normalne polecenia OpenSpec wobec tego magazynu, np.:
  openspec new change <change-id> --store team-plans
Udostępnij ten magazyn, commitując i pushując go jak każde repozytorium Git.
bash
openspec new change add-login --store team-plans
Używam korzenia OpenSpec: team-plans (/Users/you/openspec/team-plans)
Utworzono zmianę 'add-login' w /Users/you/openspec/team-plans/openspec/changes/add-login/
Schemat: spec-driven
Dalej: openspec status --change add-login --store team-plans

To cały model. Od tego momentu cykl życia jest dokładnie taki, jaki znasz – status, instructions, validate, archive – z --store team-plans przy każdym poleceniu, a każda wyświetlana podpowiedź niesie tę flagę za ciebie. Linia Używam korzenia OpenSpec: zawsze mówi, gdzie działa polecenie.

Opowieść: jeden zespół, jedno repozytorium planistyczne ​

Zespół przechowuje swoje specyfikacje i zmiany w team-plans, zamiast rozpraszać je po repozytoriach kodu.

Dzień pierwszy (ktoś to konfiguruje):

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

Podanie --remote zapisuje adres URL klonowania w pliku tożsamości magazynu (.openspec-store/store.yaml), w początkowym commicie. Każdy przyszły klon od razu wie, skąd pochodzi, więc sprawdzenia poprawności i komunikaty błędów mogą wyświetlić kompletną, gotową do wklejenia poprawkę dla kolegów, którzy jeszcze go nie mają.

Każdy członek zespołu (raz na maszynę):

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

Od tej pory wszyscy pracują w tym samym repozytorium planistycznym, używając nazwy:

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

Dzielenie się pracą to git, celowo. Zmiana, którą tworzysz, istnieje tylko w twojej kopii roboczej, dopóki jej nie skomitujesz i nie wypchniesz – tak samo jak kod. Plany zyskują gałęzie, pull requesty i przegląd za darmo, ponieważ magazyn jest zwykłym repozytorium.

Łączenie repozytoriów kodu zespołu. Repozytorium kodu, którego planowanie jest w pełni zewnętrzne, potrzebuje dokładnie jednej linii w openspec/config.yaml:

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

Teraz każde polecenie OpenSpec uruchomione wewnątrz web-app działa na team-plans bez żadnych flag:

bash
cd ~/src/web-app
openspec status --change add-login
Używam korzenia OpenSpec: team-plans (/Users/you/openspec/team-plans)
...

Wskazanie jest wartością domyślną, a nie nadpisaniem: jawny --store zawsze wygrywa, a jeśli repozytorium wyrośnie później własne foldery planowania, one wygrywają (z ostrzeżeniem o usunięciu nieaktualnego wskazania).

Jedna wartość domyślna dla każdego repozytorium na twojej maszynie. Jeśli pracujesz w wielu repozytoriach kodu, które wszystkie planują do tego samego magazynu, ustaw go raz, globalnie, zamiast dodawać linię store: do każdego repozytorium:

bash
openspec config set defaultStore team-plans

Teraz każde polecenie uruchomione poza korzeniem planowania – i bez --store oraz bez wskazania projektu – kieruje do team-plans. Znajduje się ono na dole listy priorytetów, więc --store, lokalny korzeń i wskazanie store: w projekcie wciąż wygrywają. Baner korzenia i blok root w JSON-ie raportują source: "global_default" z identyfikatorem magazynu, dzięki czemu zawsze odróżnisz globalną wartość domyślną od wskazania w repozytorium. Wyczyść to przez openspec config unset defaultStore. Jeśli identyfikator nie jest zarejestrowany, polecenia zgłaszają błąd i mówią, aby go zarejestrować lub wyczyścić nieaktualną wartość domyślną.

Przykład: jedna funkcja, dwa repozytoria komponentów ​

Załóżmy, że add-checkout-promo zmienia zarówno checkout-api, jak i checkout-web. Zespół chce jeden wspólny kontrakt produktu, podczas gdy każde repozytorium kodu nadal potrzebuje własnych zadań implementacyjnych, gałęzi i przeglądu.

Użyj dwóch warstw:

  1. Przechowuj wspólne zachowanie w team-plans.
  2. Przechowuj plany implementacyjne w każdym repozytorium komponentu i odwołuj się do magazynu jako kontekstu nadrzędnego tylko do odczytu.

Najpierw zaplanuj wspólny kontrakt w magazynie:

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

Propozycja i specyfikacje powinny opisywać zachowanie na granicy między komponentami – na przykład pola promocji zwracane przez usługę i sposób, w jaki frontend obsługuje nieuprawniony checkout. Przejrzyj tę zmianę w repozytorium magazynu jak każdą inną gałąź i pull request.

Jaki kontekst widzi planista? ​

Wybranie magazynu zmienia korzeń OpenSpec; nie odkrywa on ani nie odczytuje każdego repozytorium kodu, które z niego korzysta. Instrukcje magazynu widzą artefakty i skonfigurowany kontekst w magazynie. Widzą kod komponentów tylko wtedy, gdy te foldery są również dostępne dla agenta lub edytora i agent je odczyta.

Workset jest wygodnym sposobem na otwarcie magazynu planowania i obu repozytoriów kodu razem:

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

To sprawia, że foldery są widoczne w jednej przestrzeni roboczej IDE. Nie kopiuje to kontekstu źródłowego do magazynu, nie wybiera dotkniętych repozytoriów ani nie daje agentowi uprawnień do ich edycji. Umieszczaj trwałe fakty międzykomponentowe we wspólnych specyfikacjach; nie polegaj na tym, że planista zapamięta źródło, które przypadkiem zbadał.

Jak rozpoczyna się implementacja w każdym repozytorium? ​

Gdy nie ma jawnego --store ani bliższego korzenia openspec/, wskazanie store: team-plans kieruje polecenia do tego magazynu. Nie dzieli to jednej listy zadań magazynu według katalogu, z którego wywołano apply. OpenSpec obecnie nie kieruje zadań do repozytoriów.

Gdy każdy komponent potrzebuje niezależnego cyklu apply/review, daj mu lokalny korzeń OpenSpec i odwołuj się do centralnego magazynu zamiast na niego wskazywać:

yaml
# checkout-api/openspec/config.yaml (i podobnie w checkout-web)
schema: spec-driven
references:
  - team-plans

Po zatwierdzeniu wspólnego kontraktu i udostępnieniu go w głównych specyfikacjach magazynu, utwórz małą lokalną zmianę dla części komponentowej:

bash
cd ~/src/checkout-api
openspec new change implement-checkout-promo-api

cd ~/src/checkout-web
openspec new change implement-checkout-promo-ui

Indeks odwołań w instrukcjach każdego repozytorium dostarcza podsumowanie specyfikacji z magazynu oraz dokładne polecenie pobrania openspec show ... --store team-plans. Każda lokalna propozycja powołuje się na ten wspólny kontrakt, a jej zadania opisują tylko pracę w tym komponencie. Następnie uruchom /opsx:apply osobno w każdym repozytorium; rozwiązywanie korzenia utrzymuje artefakty i edycje implementacyjne w zakresie tego repozytorium. Zmiany w usłudze i frontendzie mogą teraz być testowane, przeglądane, scalane i archiwizowane niezależnie.

Jeśli implementacja musi się rozpocząć, gdy zmiana w magazynie jest nadal aktywna, pobierz ją jawnie przez openspec show add-checkout-promo --store team-plans; indeksy odwołań wymieniają kanoniczne specyfikacje magazynu, a nie aktywne zmiany magazynu. Utrzymuj gałąź magazynu i gałęzie komponentów połączone w opisach pull requestów, aby recenzenci mogli zobaczyć, za którą wersją kontraktu podąża każda implementacja.

Opowieść: wymagania przecinające granice zespołów ​

Zespół platformowy jest właścicielem wymagań. Zespoły produktowe budują na ich podstawie, w swoich własnych repozytoriach, z własnymi projektami. Odwołanie opisuje tę relację, nie przenosząc niczyjej pracy.

   platform-reqs (magazyn)                 api-server (repo kodu)
   własność zespołu platformowego          własność zespołu produktowego
   ┌──────────────────────────┐            ┌──────────────────────────┐
   │ openspec/specs/          │ ◀──────────│ openspec/config.yaml     │
   │   payments/spec.md       │ odczytuje  │   references:            │
   │   auth/spec.md           │            │     - platform-reqs      │
   │                          │            │ openspec/specs/          │
   │ openspec/changes/        │            │   (ich własne projekty)  │
   │   praca platformowa      │            │ openspec/changes/        │
   │                          │            │   (ich własna praca)     │
   │                          │            └──────────────────────────┘
   └──────────────────────────┘

Zespół produktowy deklaruje, z czego korzysta w pliku openspec/config.yaml swojego repozytorium:

yaml
references:
  - platform-reqs

Odwołania to kontekst tylko do odczytu. Repozytorium zachowuje swój własny korzeń openspec/; praca pozostaje tam. Co się zmienia: openspec instructions w tym repozytorium zawiera teraz indeks specyfikacji odniesionego magazynu – każda z jednozdaniowym podsumowaniem i dokładnym poleceniem pobrania (openspec show <spec-id> --type spec --store platform-reqs). Agent pracujący w api-server może znaleźć nadrzędne wymagania płatności, zacytować je i napisać swój niskopoziomowy projekt w korzeniu własnego repozytorium – bez konieczności przeklejania kontekstu przez kogokolwiek.

Odwołanie może nieść swoje źródło klonowania, dzięki czemu koledzy, którzy nie mają jeszcze magazynu, otrzymują kompletną naprawę zamiast ślepego zaułka:

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

Gdy chcesz mieć plan i kod otwarte razem, utwórz workset. Jest to osobiste i jawne: każda osoba wybiera foldery, z którymi faktycznie pracuje na swojej maszynie. Nic o tych lokalnych ścieżkach nie jest committowane do współdzielonego repozytorium planowania.

bash
openspec workset create platform \
  --member ~/openspec/platform-reqs \
  --member ~/src/api-server \
  --member ~/src/web-app

Dwa pytania, które zawsze możesz zadać ​

"Czy moja konfiguracja jest zdrowa?" – openspec doctor sprawdza bieżący korzeń i jego odniesione magazyny, tylko do odczytu, z gotową do wklejenia poprawką dla każdego znaleziska:

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

"Z czym pracuję?" – openspec context zestawia zestaw roboczy z deklaracji OpenSpec: korzeń i magazyny, do których się odwołuje.

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

Obydwa wspierają --json dla agentów. openspec context --code-workspace <path> dodatkowo zapisuje plik przestrzeni roboczej VS Code zawierający cały zestaw – jedyny zapis, jaki wykonuje to polecenie.

Worksets: ponowne otwieranie folderów, nad którymi wspólnie pracujesz ​

Osobno od wszystkiego powyżej: większość osób otwiera te same kilka folderów razem w każdej sesji — repozytorium planowania oraz dwa lub trzy repozytoria kodu. Workset to osobisty, nazwany widok dokładnie tego zestawu, ponownie otwierany jedną komendą w wybranym narzędziu.

  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 tool
bash
openspec workset create platform \
  --member ~/openspec/team-plans --member ~/src/api-server \
  --tool code
openspec workset list
platform  (opens in VS Code)
  team-plans  /Users/you/openspec/team-plans
  api-server  /Users/you/src/api-server

openspec workset open platform uruchamia następnie zapisane narzędzie: edytory (VS Code, Cursor) otwierają jedno okno z każdym członkiem i zwracają. Pierwszy członek jest główny. Narzędzie można w dowolnym momencie nadpisać za pomocą --tool <id>.

Worksets celowo nie są współdzielonym stanem. Istnieją na Twoim komputerze, nigdy nie są commitowane i nie formułują żadnych twierdzeń o pracy — jedynie rejestrują, co lubisz otwierać razem. Usunięcie jednego nigdy nie dotyka folderów członków. Nowe narzędzia to konfiguracja, nie kod: wszystko, co uruchamiane za pomocą pliku roboczego lub flag attach per-folder, może zostać dodane pod kluczem openers w globalnej konfiguracji (openspec config edit).

Jak komendy decydują, gdzie działać ​

Każda zwykła komenda rozwiązuje swój root w ten sam sposób, w tej kolejności:

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)

Linia Using OpenSpec root: (oraz blok root w wyjściu --json) informuje Cię, w którym przypadku jesteś.

Znane ograniczenia ​

  • Forma beta. Wszystko na tej stronie może ulec zmianie między wydaniemiami — nazwy, flagi, formaty plików, klucze JSON.
  • Jeden checkout na identyfikator magazynu na komputer. Rejestrowanie drugiego checkoutu pod tym samym identyfikatorem kończy się błędem z podpowiedzią, aby najpierw wykonać store unregister.
  • Brak synchronizacji, nigdy — zgodnie z projektem. OpenSpec nigdy nie klonuje, nie pobiera ani nie wysyła. Stary checkout wyświetla stare specyfikacje, dopóki Ty nie pobierzesz; odniesienia są indeksowane na żywo z tego, co znajduje się na dysku.
  • Puste foldery planowania mogą być nieobecne. Nowy magazyn może nie mieć jeszcze openspec/changes/, openspec/specs/ lub openspec/changes/archive/ w Git. Jest to akceptowane podczas wersji beta; te foldery pojawią się, gdy zwykłe komendy utworzą dla nich pliki.
  • Repozytoria wskaźnikowe pozostają wskaźnikami. Repozytorium zawierające wyłącznie konfigurację, którego openspec/config.yaml deklaruje store: <id>, jest traktowane jako zewnętrznione planowanie, a nie jako checkout magazynu do zarejestrowania. Najpierw usuń linię store:, jeśli celowo chcesz przekonwertować to repozytorium na lokalny root magazynu.
  • Niektóre komendy pozostają tam, gdzie są. templates oraz nieaktualne formy rzeczownikowe (openspec change show, ...) działają wyłącznie na bieżący katalog — bez --store. schemas podąża za kanonicznym priorytetem wyboru roota i akceptuje --store <id>, zachowując niezmienioną strukturę tablicy JSON przy pomyślnym zakończeniu.
  • Stan per-komputer to stan per-komputer. Rejestr magazynów i worksets to ustawienia lokalne. Nic o układzu Twojego komputera nigdy nie jest commitowane do wspólnego planowania.
  • Dwa style uruchamiania worksets. Narzędzie, którego nie można uruchomić za pomocą pliku roboczego lub flag attach per-folder, nie może zostać dodane jako opener.
  • JSON agenta ma znany podział wielkości liter (klucze rodziny store są w snake_case, klucze rodziny workflow w camelCase). Udokumentowane w umowie agenta; ujednolicenie jest odłożone na wydanie z wersjonowaniem.

Gdzie znajdują się poszczególne elementy ​

CoGdzieWspółdzielone?
Planowanie magazynu<store>/openspec/ (specyfikacje, zmiany)Tak — commituj i pushuj
Tożsamość magazynu<store>/.openspec-store/store.yamlTak — commitowane z magazynem
Rejestr magazynów<data dir>/openspec/stores/registry.yamlNie — tylko ten komputer
Worksets<data dir>/openspec/worksets/Nie — tylko ten komputer

<data dir> to ~/.local/share/openspec na macOS i Linux (lub $XDG_DATA_HOME/openspec, gdy ustawione), oraz %LOCALAPPDATA%\openspec na Windows.

Referencja ​

Dokładne flagi i struktury JSON dla każdej komendy na tej stronie: referencja CLI (Stores, Doctor, Working context, Personal worksets) oraz umowa agenta.