Stores: pianificare nel proprio repo
Beta. Stores, references, working context e worksets sono nuovi. Nomi dei comandi, flag, formati di file e output JSON potrebbero ancora cambiare forma tra le release. Ogni procedura descritta di seguito è stata eseguita con la build corrente, ma rileggi questa guida dopo un aggiornamento.
Il problema che risolve
OpenSpec normalmente vive all'interno di un singolo repository di codice: una cartella openspec/ accanto al tuo codice, che contiene spec e modifiche per quel repository.
Questo smette di funzionare nel momento in cui la tua pianificazione è più ampia di un singolo repository:
- Il tuo lavoro si estende su più repository: una funzionalità tocca il server API, l'app web e una libreria condivisa. In quale cartella
openspec/risiede il piano? - Il tuo team pianifica prima che il codice esista, o pianifica cose che non diventeranno mai codice in questo repo.
- I requisiti sono di proprietà di un team e consumati da altri. La versione wiki si discosta, e il tuo coding agent non può comunque leggerli.
Un store è la risposta: un repository autonomo il cui intero compito è la pianificazione. Ha la stessa struttura openspec/ che già conosci — spec e modifiche — più un piccolo file di identità. Lo registri sulla tua macchina una volta, per nome, e poi ogni normale comando OpenSpec può lavorarci da qualsiasi luogo.
La struttura
team-plans (un archivio: pianificazione nel proprio repo)
├── .openspec-store/store.yaml identity: "I am team-plans"
└── openspec/
├── specs/ cosa è vero
└── changes/ cosa è in movimento
▲
│ registrato su ogni macchina per nome;
│ condiviso tramite push/cloning come qualsiasi altro repo
┌─────────────┼─────────────┐
│ │ │
web-app api-server mobile-app
(repo del codice) (repo del codice) (repo del codice)Due regole mantengono tutto semplice:
- Un archivio è semplicemente un repo git. Lo si commita, fa push, pull e revisiona autonomamente. OpenSpec non clona, sincronizza o effettua mai push di nulla da solo.
- Dichiarazioni, non meccanismi. I repo possono dichiarare come si relazionano con gli archivi (mostrato di seguito). Le dichiarazioni cambiano ciò che OpenSpec può dirti — mai dove agiscono i tuoi comandi.
Cinque minuti al tuo primo archivio
Due comandi ti portano da zero a una modifica funzionante e limitata all'archivio:
openspec store setup team-plans --path ~/openspec/team-plansStore pronto: team-plans
Posizione: /Users/you/openspec/team-plans
Radice OpenSpec: pronta
Registro: registrato
Prossimo: esegui i normali comandi OpenSpec su questo archivio, ad esempio:
openspec new change <change-id> --store team-plans
Condividi questo archivio facendone il commit e il push come faresti con qualsiasi repo Git.openspec new change add-login --store team-plansUtilizzo della radice OpenSpec: team-plans (/Users/you/openspec/team-plans)
Creata la modifica 'add-login' in /Users/you/openspec/team-plans/openspec/changes/add-login/
Schema: spec-driven
Prossimo: openspec status --change add-login --store team-plansQuesto è l'intero modello. Da qui il ciclo di vita è esattamente quello che già conosci — status, instructions, validate, archive — con --store team-plans su ogni comando, e ogni suggerimento stampato include il flag per te. La riga Using OpenSpec root: indica sempre dove sta agendo un comando.
Storia: un team, un repo di pianificazione
Un team mantiene le sue specifiche e le modifiche in team-plans invece di spargerle tra i repo del codice.
Giorno uno (chiunque lo configuri):
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 mainPassando --remote si registra l'URL di clonazione all'interno del file di identità stesso dell'archivio (.openspec-store/store.yaml), nel commit iniziale. Ogni futuro clone nasce sapendo da dove proviene, così i controlli di integrità e i messaggi di errore possono stampare una correzione completa e incollabile per i colleghi che non ce l'hanno ancora.
Ogni collega (una volta per macchina):
git clone git@github.com:acme/team-plans.git ~/openspec/team-plans
openspec store register ~/openspec/team-plansDa quel momento, tutti lavorano nello stesso repo di pianificazione per nome:
openspec status --store team-plans --change add-login
openspec show add-login --store team-plansLa condivisione del lavoro è git, per scelta. Una modifica che crei esiste solo nel tuo checkout finché non ne fai il commit e il push — uguale al codice. I piani ottengono rami, pull request e revisione gratuitamente, perché un archivio è un repo ordinario.
Collegamento dei repo del codice del team. Un repo del codice la cui pianificazione è completamente esternalizzata ha bisogno di esattamente una riga, in openspec/config.yaml:
# web-app/openspec/config.yaml
store: team-plansOra ogni comando OpenExec eseguito all'interno di web-app agisce su team-plans senza alcun flag:
cd ~/src/web-app
openspec status --change add-loginUtilizzo della radice OpenSpec: team-plans (/Users/you/openspec/team-plans)
...Il puntatore è un fallback, mai un override: un --store esplicito vince sempre, e se il repo cresce cartelle di pianificazione proprie, quelle vincono (con un avviso per rimuovere il puntatore obsoleto).
Un default per ogni repo sulla tua macchina. Se lavori tra molti repo del codice che pianificano tutti nello stesso archivio, impostalo una volta, globalmente, invece di aggiungere la riga store: a ciascun repo:
openspec config set defaultStore team-plansOra qualsiasi comando eseguito al di fuori di una radice di pianificazione — e senza --store né puntatore di progetto — risolve verso team-plans. Si trova in fondo alla lista di precedenza, quindi --store, una radice locale e un puntatore store: di progetto vincono comunque. Il banner della radice e il blocco JSON root riportano source: "global_default" con l'id dell'archivio, così puoi sempre distinguere un default su tutta la macchina dal puntatore di un repo. Cancella con openspec config unset defaultStore. Se l'id non è registrato, i comandi restituiscono un errore e ti indicano di registrarlo o cancellare il default obsoleto.
Esempio: una funzionalità, due repo di componenti
Supponiamo che add-checkout-promo modifichi sia checkout-api che checkout-web. Il team vuole un contratto di prodotto condiviso, mentre ogni repo del codice ha comunque bisogno delle proprie attività di implementazione, ramo e revisione.
Usa due livelli:
- Mantieni il comportamento condiviso in
team-plans. - Mantieni i piani di implementazione in ciascun repo del componente e fai riferimento all'archivio come contesto upstream in sola lettura.
Prima, pianifica il contratto condiviso nell'archivio:
openspec new change add-checkout-promo --store team-plans
openspec status --change add-checkout-promo --store team-plansLa proposta e le specifiche dovrebbero descrivere il comportamento al confine tra i componenti — ad esempio, i campi di promozione restituiti dal servizio e come il frontend gestisce un checkout non idoneo. Rivedi questa modifica nel repo dell'archivio come faresti con qualsiasi altro ramo e pull request.
Quale contesto vede la pianificazione?
Selezionare un archivio cambia la radice di OpenSpec; non scopre né legge ogni repo del codice che utilizza quell'archivio. Le istruzioni dell'archivio vedono gli artefatti e il contesto configurato nell'archivio. Vedono il codice del componente solo quando quelle cartelle sono anche disponibili per l'agente o l'editor e l'agente le legge.
Un workset è un modo conveniente per aprire contemporaneamente l'archivio di pianificazione e entrambi i repo del codice:
openspec workset create checkout-promo \
--member ~/openspec/team-plans \
--member ~/src/checkout-api \
--member ~/src/checkout-web \
--tool code
openspec workset open checkout-promoQuesto rende le cartelle visibili in un'unica area di lavoro IDE. Non copia il contesto del sorgente nell'archivio, seleziona i repo interessati o concede all'agente il permesso di modificarli. Inserisci fatti duraturi cross-componente nelle specifiche condivise; non fare affidamento sul fatto che un pianificatore ricordi il sorgente che ha casualmente ispezionato.
Come inizia l'implementazione in ciascun repo?
Quando non si applica un --store esplicito né una radice openspec/ più vicina, un puntatore store: team-plans instrada i comandi verso quell'archivio. Non divide l'elenco dei task di un archivio in base alla directory da cui è stato invocato apply. OpenSpec attualmente non instrada i task verso i repo.
Quando ogni componente ha bisogno di un ciclo apply/review con ambito indipendente, forniscigli una radice OpenSpec locale e fai riferimento all'archivio centrale invece di puntargli:
# checkout-api/openspec/config.yaml (e analogamente in checkout-web)
schema: spec-driven
references:
- team-plansDopo che il contratto condiviso è approvato e disponibile nelle specifiche principali dell'archivio, crea una piccola modifica locale per la parte del componente:
cd ~/src/checkout-api
openspec new change implement-checkout-promo-api
cd ~/src/checkout-web
openspec new change implement-checkout-promo-uiL'indice dei riferimenti nelle istruzioni di ciascun repo fornisce il riepilogo della specifica dell'archivio e il comando di fetch esatto (openspec show ... --store team-plans). Ogni proposta locale cita quel contratto condiviso, e le sue attività descrivono solo il lavoro in quel componente. Quindi esegui /opsx:apply in ciascun repo separatamente; la risoluzione della radice mantiene gli artefatti e le modifiche di implementazione limitate a quel repo. Le modifiche del servizio e del frontend possono ora essere testate, revisionate, unite e archiviate indipendentemente.
Se l'implementazione deve iniziare mentre la modifica dell'archivio condiviso è ancora attiva, recuperarla esplicitamente con openspec show add-checkout-promo --store team-plans; gli indici dei riferimenti elencano specifiche canoniche dell'archivio, non modifiche attive dell'archivio. Manteni il ramo dell'archivio e i rami dei componenti collegati nelle loro descrizioni delle pull request così i revisori possono vedere quale versione del contratto segue ciascuna implementazione.
Storia: requisiti che attraversano i confini del team
Un team di piattaforma possiede i requisiti. I team di prodotto costruiscono contro di essi, nei propri repo, con i propri design. Un riferimento descrive quella relazione senza spostare il lavoro di nessuno.
platform-reqs (archivio) api-server (repo del codice)
di proprietà del team di piattaforma di proprietà di un team di prodotto
┌──────────────────────────┐ ┌──────────────────────────┐
│ openspec/specs/ │ ◀────────│ openspec/config.yaml │
│ payments/spec.md │ legge │ references: │
│ auth/spec.md │ │ - platform-reqs │
│ │ │ openspec/specs/ │
│ │ │ (loro propri design) │
│ openspec/changes/ │ │ openspec/changes/ │
│ lavoro piattaforma │ │ (loro proprio lavoro) │
│ │ └──────────────────────────┘
└──────────────────────────┘Il team di prodotto dichiara su cosa attinge nel suo repo's openspec/config.yaml:
references:
- platform-reqsI riferimenti sono contesto in sola lettura. Il repo mantiene la propria radice openspec/; il lavoro rimane lì. Cosa cambia: openspec instructions in quel repo ora include un indice delle specifiche dell'archivio referenziato — ciascuna con un riepilogo di una riga e il comando di fetch esatto (openspec show <spec-id> --type spec --store platform-reqs). Un agente che lavora in api-server può trovare i requisiti di pagamento upstream, citarli e scrivere il proprio design a basso livello nella radice del repo — senza che nessuno debba incollare il contesto.
Un riferimento può trasportare la sua origine di clonazione, così i colleghi che non hanno ancora l'archivio ricevono una correzione completa invece di un vicolo cieco:
references:
- { id: platform-reqs, remote: "git@github.com:acme/platform-reqs.git" }Quando vuoi aprire piano e codice insieme, crea un workset. Questo è personale ed esplicito: ogni persona sceglie le cartelle con cui effettivamente lavora sulla propria macchina. Nulla di questi percorsi di checkout locali viene commitato nel repo di pianificazione condiviso.
openspec workset create platform \
--member ~/openspec/platform-reqs \
--member ~/src/api-server \
--member ~/src/web-appDue domande che puoi sempre porre
"È sano il mio setup?" — openspec doctor controlla la radice corrente e i suoi archivi referenziati, in sola lettura, con una correzione incollabile per ogni rilevamento:
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"Con cosa sto lavorando?" — openspec context assembla l'insieme di lavoro dalle dichiarazioni di OpenSpec: la radice e gli archivi che essa referenzia.
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-reqsEntrambi supportano --json per gli agenti. openspec context --code-workspace <path> scrive inoltre un file dell'area di lavoro VS Code contenente l'insieme completo — l'unica scrittura che questo comando esegue.
Worksets: riapri le cartelle su cui lavori insieme
Separato da tutto quanto sopra: la maggior parte delle persone apre le stesse poche cartelle insieme a ogni sessione — il repository di pianificazione più due o tre repository di codice. Un workset è una vista personale e nominata di esattamente ciò, riaperta con un solo comando nel tuo strumento preferito.
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-serveropenspec workset open platform avvia quindi lo strumento salvato: gli editor (VS Code, Cursor) aprono una finestra con tutti i membri e restituiscono il controllo. Il primo membro è quello primario. È possibile sovrascrivere lo strumento in qualsiasi momento con --tool <id>.
I workset sono deliberatamente non uno stato condiviso. Vivono sulla tua macchina, non vengono mai committati e non fanno alcuna affermazione sul lavoro — registrano solo ciò che ti piace avere aperto insieme. La rimozione di uno non tocca mai le cartelle dei membri. I nuovi strumenti sono configurazione, non codice: qualsiasi cosa avviata tramite un file workspace o flag di allegamento per cartella può essere aggiunta sotto la chiave openers nella configurazione globale (openspec config edit).
Come i comandi decidono dove agire
Ogni comando normale risolve la propria radice nello stesso modo, in questo ordine:
1. --store <id> l'hai specificato esplicitamente → quello store
2. nearest openspec/ una vera radice di pianificazione qui → questo repo
(salendo da cwd)
3. store: pointer config.yaml dichiara uno store → quello store
4. defaultStore la configurazione globale imposta una → quello store
macchina predefinita
5. nessuno dei precedenti store registrati su questa → errore con un
macchina? suggerimento di selezione
nessun store registrato? → la directory
corrente
(comportamento classico)La riga Using OpenSpec root: (e il blocco root nell'output --json) ti indica in quale caso ti trovi.
Limitazioni note
- Forma beta. Tutto su questa pagina può cambiare tra un rilascio e l'altro — nomi, flag, formati di file, chiavi JSON.
- Un checkout per store id per macchina. Registrare un secondo checkout con lo stesso id fallisce con un suggerimento di eseguire prima
store unregister. - Nessuna sincronizzazione, mai — per design. OpenSpec non clona, non tira e non spinge mai. Un checkout obsoleto mostra specifiche obsolete finché tu non esegui pull; i riferimenti sono indicizzati in tempo reale da ciò che è su disco.
- Le cartelle di pianificazione vuote possono essere assenti. Un nuovo store potrebbe non avere ancora
openspec/changes/,openspec/specs/oopenspec/changes/archive/in Git. Questo è accettato durante la beta; quelle cartelle appaiono una volta che i comandi normali creano file per esse. - I repository puntatore restano puntatori. Un repository solo di configurazione il cui
openspec/config.yamldichiarastore: <id>è trattato come pianificazione esternalizzata, non come un checkout di store da registrare. Rimuovi prima la rigastore:se vuoi intenzionalmente convertire quel repository in una radice di store locale. - Alcuni comandi restano dove sono.
templatese le forme sostantive deprecate (openspec change show, ...) agiscono solo sulla directory corrente — nessun--store.schemassegue la precedenza canonica di selezione della radice e accetta--store <id>mantenendo invariata la sua forma di array JSON di successo. - Lo stato per macchina è per macchina. Il registro degli store e i workset sono impostazioni locali. Nulla riguardo alla disposizione della tua macchina viene mai committato nella pianificazione condivisa.
- Due stili di avvio per i workset. Uno strumento che non può essere avviato con un file workspace o flag di allegamento per cartella non può essere aggiunto come opener.
- Il JSON dell'agent ha una nota divisione di casse (le chiavi della famiglia store sono snake_case, quelle della famiglia workflow camelCase). Documentato nel agent contract; l'unificazione è rimandata a un rilascio versionato.
Dove risiedono le cose
| Cosa | Dove | Condiviso? |
|---|---|---|
| La pianificazione di uno store | <store>/openspec/ (specs, changes) | Sì — committalo e spingilo |
| L'identità di uno store | <store>/.openspec-store/store.yaml | Sì — committato con lo store |
| Il registro degli store | <data dir>/openspec/stores/registry.yaml | No — solo questa macchina |
| I workset | <data dir>/openspec/worksets/ | No — solo questa macchina |
<data dir> è ~/.local/share/openspec su macOS e Linux (o $XDG_DATA_HOME/openspec quando impostato), e %LOCALAPPDATA%\openspec su Windows.
Riferimento
Flag esatti e forme JSON per ogni comando su questa pagina: CLI reference (Stores, Doctor, Working context, Personal worksets) e il agent contract.