Skip to content

Stores (beta) ​

Lên kế hoạch cho những thay đổi trải rộng nhiều repository: một store, nhiều repo.

OpenSpec thường nằm trong một repo: một thư mục openspec/ đặt cạnh phần code mà nó lên kế hoạch. Store chuyển thư mục đó vào một repository riêng, và nhiều code repo có thể dùng chung nó.

Sau khi thiết lập một lần trên mỗi máy, các lệnh như status, new change và archive có thể hoạt động trong store từ bất kỳ thư mục nào.

         team-plans  (một store: OpenSpec trong repo riêng của nó)
         ├── .openspec-store/store.yaml   tên của store
         └── openspec/
             ├── specs/
             └── changes/
                   ▲
                   │ thiết lập một lần trên mỗi máy,
                   │ chia sẻ bằng push và clone như bất kỳ repo nào
     ┌─────────────┼─────────────┐
     │             │             │
 web-app       api-server     mobile-app
(code repo)   (code repo)    (code repo)

Bạn chia sẻ store bằng git, giống như cách bạn chia sẻ code: tự commit, push, pull và review nó. Specs và changes cũng có branch và pull request giống như code.

Khi nào bạn cần dùng ​

Hai lý do phổ biến để dùng store:

  • Frontend và backend ở các repo riêng biệt: một feature động đến cả hai, và kế hoạch cần một nơi duy nhất thay vì hai nửa.

          shop-plans  (store)
          └── openspec/changes/add-discounts/    một kế hoạch cho feature
                    ▲
          ┌─────────┴─────────┐
          │                   │
      storefront             api
    (repo frontend)     (repo backend)
  • Một sản phẩm, nhiều client repo: Android, iOS và web phát hành từ repo riêng của chúng nhưng dùng chung một hành vi mong đợi. Một spec mô tả hành vi, không phải implementation, nên một spec phục vụ cả ba.

            product-specs  (store)
            └── openspec/specs/checkout/spec.md    hành vi mong đợi
                      ▲
        ┌─────────────┼─────────────┐
        │             │             │
    android-app    ios-app       web-app
    (code repo)   (code repo)   (code repo)

Bạn có thể có nhiều hơn một store, tuy nhiên chúng tôi khuyến nghị giữ số lượng ở mức thấp.

Thiết lập một store ​

Một người tạo store, sau đó mọi người khác tham gia vào.

  1. Tạo store (một người, một lần cho mỗi nhóm). Chạy openspec store setup và trả lời các câu hỏi:

    bash
    # chạy từ bất kỳ đâu; nó sẽ hỏi bạn muốn tạo gì và ở đâu
    openspec store setup

    Nó đặt ba câu hỏi:

    • Store name: team-plans
    • Where should this store live?: đã điền sẵn ~/openspec/<name>, nhấn Enter để chấp nhận hoặc nhập một đường dẫn khác
    • Create this store?: hiển thị những gì nó sắp tạo, trả lời Yes

    Sau đó nó báo cáo những gì đã tạo:

    yaml
    Store ready: team-plans
    Location: ~/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.
  2. Đẩy nó lên git host của bạn. Tạo một repo team-plans trống trên host của bạn trước. Setup không thêm git remote, vì vậy hãy kết nối store với repo đó, sau đó push:

    bash
    # kết nối store với repo trống trên git host của bạn
    cd ~/openspec/team-plans
    git remote add origin git@github.com:acme/team-plans.git
    
    # xuất bản nó
    git push -u origin main
  3. Tham gia store (mỗi đồng đội, một lần cho mỗi máy):

    bash
    # lấy store về máy của bạn
    git clone git@github.com:acme/team-plans.git ~/openspec/team-plans
    
    # cho OpenSpec biết nó nằm ở đâu
    openspec store register ~/openspec/team-plans
    yaml
    Store registered: team-plans
    Location: /Users/you/openspec/team-plans
    OpenSpec root: ready
    Registry: registered

    Đăng ký cho máy của bạn biết store nằm ở đâu. Tên của store đã được commit bên trong nó, trong .openspec-store/store.yaml. Setup đã đăng ký bản sao của người tạo, vì vậy chỉ các bản sao được clone mới cần bước này.

  4. Xác nhận nó hoạt động, từ bất kỳ thư mục nào:

    bash
    # bất kỳ lệnh OpenSpec nào cũng đến store bằng tên
    openspec status --store team-plans
    yaml
    Using OpenSpec root: team-plans (/Users/you/openspec/team-plans)
    No active changes. Create one with: openspec new change <name> --store team-plans

Các loại thiết lập ​

OpenSpec có ba loại thiết lập. Phần còn lại của trang này sử dụng các tên này:

  • repo-local: OpenSpec bên trong repo của bạn, không có store. Mặc định.
  • store-only: repo của bạn không giữ specs hoặc changes riêng. Mọi thứ nằm trong store.
  • store-optional: dự án của bạn có thư mục openspec/ riêng và cũng kết nối đến một store khi bạn yêu cầu.

Mặc định: OpenSpec bên trong repo của bạn (repo-local) ​

openspec init đặt một thư mục openspec/ bên cạnh code của bạn, và specs và changes của repo đó nằm ở đó. Không có store nào liên quan. Đây là thiết lập mà Thiết lập dự án của bạn hướng dẫn, và hầu hết các dự án không bao giờ cần thiết lập khác.

web-app  (code repo)
└── openspec/
    ├── specs/
    └── changes/

OpenSpec bên ngoài repo của bạn, trong một store (store-only) ​

Repo không giữ specs hoặc changes riêng. Mọi thứ nó lên kế hoạch nằm trong store, và một dòng trong config của repo kết nối hai thứ này.

Phổ biến khi một nhóm xây dựng tất cả các repo và lên kế hoạch ở một nơi. Tất cả các ví dụ ở trên đều có hình dạng này.

team-plans  (store)
└── openspec/
    ├── specs/       specs của repo nằm ở đây
    └── changes/     changes của nó cũng vậy
          ▲
          │ store: team-plans   (đường kết nối)
web-app  (code repo)
└── openspec/
    └── config.yaml    không có gì khác

OpenSpec trong repo của bạn và trong một store (store-optional) ​

Repo vẫn là repo-local cho công việc riêng của nó, trong khi store chứa specs và changes dùng chung. Bên trong repo, OpenSpec sử dụng thư mục openspec/ của dự án bạn, và chỉ kết nối đến store khi bạn truyền --store.

Phổ biến khi một repo đã sử dụng OpenSpec trước khi store tồn tại, hoặc khi một repo độc lập chủ yếu chỉ thỉnh thoảng chạm vào công việc dùng chung.

team-plans  (store)
└── openspec/          specs và changes dùng chung
          ▲
          │ chỉ khi bạn truyền --store team-plans
web-app  (code repo)
└── openspec/          của chính repo này
    ├── config.yaml
    ├── specs/
    └── changes/

Một repo có thể bắt đầu với repo-local và sau đó chuyển specs và changes của nó vào store. Chuyển specs và changes của repo vào store chỉ cách thực hiện.

Nơi các artifact được tạo khi sử dụng store ​

Khi bạn sử dụng store, OpenSpec cũng phải quyết định nơi các artifact được tạo. Nó phụ thuộc vào thiết lập của bạn:

  • store-only (dự án của bạn chỉ ghi vào store): mọi artifact được tạo trong store. Dòng store: bên dưới ghi lại điều đó.
  • store-optional (dự án của bạn có thư mục openspec/ riêng và cũng sử dụng store): artifact được tạo trong dự án của bạn, trừ khi bạn chỉ định store trong yêu cầu hoặc truyền --store cho change đó. Agent của bạn sau đó mang cờ đó xuyên suốt phần còn lại của quy trình.

OpenSpec ghi artifact vào một trong hai nơi: thư mục openspec/ của dự án bạn, hoặc của store. Nó chọn theo thứ tự này, và tùy chọn đầu tiên được áp dụng sẽ thắng:

  1. --store <id> trên một lệnh. Luôn thắng, từ bất kỳ thư mục nào.
  2. Thư mục openspec/ của dự án bạn. Nếu dự án của bạn có thư mục specs/ hoặc changes/ riêng, OpenSpec sử dụng chúng.
  3. Dòng store: trong dự án bạn. Cách một dự án store-only ghi lại store của nó.
  4. defaultStore trên máy bạn. Phương án dự phòng khi không có tùy chọn nào ở trên được áp dụng.

Nếu không có tùy chọn nào được áp dụng và bạn đã đăng ký store, lệnh sẽ thất bại và liệt kê chúng. Khi id của một store khớp với tên repo của bạn trong remote origin của nó, lỗi sẽ nêu tên store đó và dòng store: chọn nó. OpenSpec không bao giờ tự chọn store theo tên, vì các repo trong các tổ chức khác nhau có thể có cùng tên.

Khi OpenSpec chọn một store, nó in Using OpenSpec root: ... trước khi in kết quả lệnh.

Dòng store: (các dự án store-only) ​

Thêm một dòng vào openspec/config.yaml của dự án bạn:

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

Mọi thứ bạn hoặc agent của bạn chạy bên trong dự án bây giờ đều sử dụng store, không cần gõ cờ:

bash
# bên trong web-app, đã kết nối
openspec status
yaml
Using OpenSpec root: team-plans (/Users/you/openspec/team-plans)
No active changes. Create one with: openspec new change <name> --store team-plans
  • Không có dòng đó: chạy một lệnh đơn giản trong dự án store-only và OpenSpec dừng lại với lỗi liệt kê các store đã đăng ký của bạn.
  • Commit nó: đồng đội clone dự án của bạn cũng nhận được dòng đó. Họ vẫn cần store được đăng ký trên máy của họ (bước 3 của Thiết lập một store), hoặc OpenSpec báo lỗi và yêu cầu họ đăng ký.
  • Bên cạnh các thư mục thực: nếu dự án của bạn cũng có thư mục specs/ hoặc changes/, OpenSpec sử dụng chúng và bỏ qua dòng đó, kèm theo cảnh báo.

Cài đặt tích hợp trong repo store-only ​

Chạy init từ thư mục gốc của code repo để cài đặt các tệp tích hợp công cụ AI mà không chuyển việc lập kế hoạch trở lại repo đó:

bash
# bên trong web-app, ở thư mục gốc repo
openspec init --tools claude
  • Tệp tích hợp: được ghi trong code repo.
  • openspec/config.yaml: được giữ nguyên từng byte, bao gồm dòng store:.
  • openspec/specs/ và openspec/changes/: không được tạo trong code repo.

OpenSpec từ chối lệnh này từ thư mục con của code repo. Chạy nó từ thư mục gốc repo.

OpenSpec cũng từ chối --language ở đây vì ngôn ngữ thuộc về config của store bên ngoài. Chạy init ở thư mục gốc store hoặc chỉnh sửa trực tiếp config đó.

defaultStore trên máy bạn ​

Đặt một lần nếu mọi dự án bạn làm việc đều sử dụng cùng một store. OpenSpec sử dụng nó làm phương án dự phòng khi không tìm thấy cờ, không có thư mục openspec/ cục bộ và không có dòng store::

bash
# sử dụng team-plans bất cứ khi nào không có gì khác chỉ định store
openspec config set defaultStore team-plans

# hoàn tác
openspec config unset defaultStore

Các lệnh giữ cục bộ. init, update, templates, schemas và các lệnh con openspec schema chỉ tác động lên thư mục hiện tại và không nhận --store.

Chuyển specs và changes của repo vào store ​

Để chuyển một repo từ repo-local sang store-only:

  1. Chuyển mọi thứ trong openspec/specs/ và openspec/changes/ của repo vào các thư mục tương tự trong store.
  2. Xóa các thư mục giờ đã trống, để thư mục openspec/ của repo chỉ chứa config.yaml.
  3. Thêm dòng store: vào config.yaml đó.

openspec status bên trong repo bây giờ bắt đầu bằng Using OpenSpec root: team-plans.

Làm việc trong store ​

Các quy trình không thay đổi, cho bạn hoặc cho agent của bạn. Propose, apply và archive chạy theo cách chúng luôn làm. Sự khác biệt duy nhất là nơi các artifact được tạo, và phần ở trên đề cập đến điều đó.

Tạo một change từ bên trong repo store-only và nó sẽ nằm trong store:

bash
# bên trong web-app; dòng store: định tuyến điều này đến team-plans
openspec new change add-login
yaml
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
  • Nơi nó đã đến: vào repo store, không phải bên cạnh code của bạn.
  • Chia sẻ nó: change chỉ tồn tại trong checkout của bạn cho đến khi bạn commit và push repo store. Đồng đội nhìn thấy nó khi họ pull. Điều tương tự áp dụng cho mọi artifact mà các quy trình ghi.
  • Đường dẫn trong tài liệu: ở bất kỳ đâu tài liệu hiển thị đường dẫn openspec/, trong thiết lập store thì thư mục đó là của store.

Khi artifact được tạo ở nơi bạn không mong đợi, openspec doctor kiểm tra thiết lập của bạn mà không thay đổi gì và in ra cách khắc phục cho mỗi phát hiện:

bash
# kiểm tra root hiện tại và các store của nó
openspec doctor
yaml
Doctor

Root
  Location: /Users/you/openspec/team-plans
  OpenSpec root: ok
  Store: team-plans (metadata ok)

References
  (none declared)

openspec context liệt kê root và các store mà thư mục hiện tại của bạn làm việc cùng, khi bạn muốn cùng một bức tranh mà không cần kiểm tra.

Để mở store và một repo trong cùng một cửa sổ trình soạn thảo, để agent của bạn có thể đọc cả hai, xem Worksets (beta).

Đọc specs từ store khác ​

Repository của bạn có thể giữ nguyên thư mục openspec/ của mình và vẫn cho phép agent của bạn đọc specs từ một store khác. Khai báo store đó dưới references: trong tệp openspec/config.yaml của repository:

yaml
# api-server/openspec/config.yaml
references:
  - team-plans

Các tham chiếu (references) là chỉ đọc. Công việc của bạn vẫn nằm trong repository của bạn, và tham chiếu chỉ thay đổi những gì agent của bạn được thông báo.

Khi một workflow tạo ra một artifact, hướng dẫn của nó sẽ được thêm chỉ mục specs của store được tham chiếu, mỗi spec kèm theo một dòng tóm tắt và lệnh chính xác để lấy nó:

xml
<referenced_stores>
<!-- Read-only upstream context. Fetch what you need; cite what you use. -->
Store team-plans (/Users/you/openspec/team-plans):
  - payments: Rules for charging and refunding customers.
  Fetch: openspec show <spec-id> --type spec --store team-plans
</referenced_stores>

Một tham chiếu cũng có thể chứa URL clone của store, dành cho các máy chưa có store đó:

yaml
references:
  - team-plans
  - { id: design-system, remote: "git@github.com:acme/design-system.git" }

Khi URL đã được khai báo, openspec doctor sẽ biến một store thiếu thành một cách khắc phục có thể dán (paste) trực tiếp:

yaml
# output wrapped to fit
References
  - team-plans: ok (/Users/you/openspec/team-plans)
  - 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

Giới hạn của bản Beta ​

  • Cấu trúc có thể thay đổi: tên lệnh, cờ (flags) và định dạng tệp có thể thay đổi giữa các phiên bản. Hãy đọc lại trang này sau khi nâng cấp.
  • Không đồng bộ, theo thiết kế: OpenSpec không bao giờ clone, pull hoặc push. Một checkout cũ sẽ hiển thị các specs cũ cho đến khi bạn pull, và các tham chiếu được đọc từ những gì có trên ổ đĩa.
  • Một checkout cho mỗi tên store: đăng ký thư mục thứ hai dưới tên đã được đăng ký trước đó sẽ thất bại, kèm theo gợi ý chạy openspec store unregister trước tiên.