You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Since #1355, specs can be nested (specs/<domain>/<capability>/spec.md), which solves organisation. What is still missing is a way to say which specs belong together and at what version.
Take an online shop whose store holds three kinds of specs:
Storefront: how customers browse, fill a cart and check out. The product team changes it every sprint, and nobody outside the team cares about its version number.
Fulfilment: how orders are picked, shipped and returned. The warehouse team trains staff and rolls out warehouse software against a specific version ("sites run fulfilment 3.x"), so a removed or changed requirement means new procedures and must be released as a new major version.
Compliance: card-data and retention rules. An auditor signs off on "compliance specs v2026.1" once a year and needs to see exactly what changed since.
These sets have different owners, audiences and release cadences. Each one needs to answer "what is in it, and which version is current?" Today OpenSpec has no concept for that:
config.yaml has schema, context and rules, but nothing about spec membership or versions.
A change's .openspec.yaml carries schema and created, not the version of the specs it touches.
The only history is git plus the dated changes/archive/ folders. They record changes, not a released state of a group of specs.
Why a hand-written manifest is not enough
The obvious workaround is a manifest per group, next to the specs:
This works until the specs move. OpenSpec does not know about the file, so:
The list drifts. Rename fulfilment/picking to fulfilment/order-picking, or add fulfilment/click-and-collect, and the manifest is silently wrong. We saw most entries go stale after a single rename pass.
The version is never bumped. Nothing ties version to archiving a change, so the number goes stale too.
The CLI and agents can't use it: list, show, validate and context ignore the grouping.
Proposal
Add first-class spec sets: a named, versioned group of specs, selected by path prefix instead of a file list.
A per-set file (specs/<name>.specset.yaml) with the same fields would also work. With prefix-based membership, adding or renaming a spec never means editing the manifest.
2. Validation
openspec validate (and doctor) should report:
a spec that matches no set, when sets are declared (opt-in, e.g. specSets.requireMembership: true);
a spec that matches more than one set;
an include entry that matches nothing.
3. CLI
openspec list --specs groups output by set and shows each set's version.
openspec list --specs --set fulfilment and openspec show --set compliance filter by set.
openspec context includes set names and versions in the agent brief.
4. Versioning on archive
openspec archive <change> already knows which specs a change touched, so it knows the affected sets. It could:
report the affected sets (for example, "this change touches Fulfilment 3.2.0");
optionally bump their version, either explicitly (--bump patch|minor|major) or derived from the delta: REMOVED requirements give a major bump, ADDED gives a minor bump, and MODIFIED gives a patch bump;
record the resulting set versions in the archived change's .openspec.yaml, so the archive shows which release each change landed in.
For the example above, archiving a change that drops the "returns accepted without a receipt" requirement would say: "Fulfilment 3.2.0 → 4.0.0 (breaking: REMOVED requirement in fulfilment/returns)". The warehouse team would see that before merging, not after the new rule reaches the sites.
A plain "report only, bump by hand" first step would already be useful.
It relates to [Feature Request] Multi-repository / microservice spec management #725 (multi-repo). A code repo could pin the set version it implements (e.g. the warehouse service declares specSets: { fulfilment: ^3.0.0 }). That gives the drift and staleness signal discussed in that thread.
Open questions
Should a set be able to include other sets (e.g. an all set)?
Should versions live in config, or be derived purely from git tags (<set>-v<version>)?
Is specSets the right name, or bundles / packages?
If the direction is agreed, I'll follow up with an OpenSpec change proposal (openspec/changes/add-spec-sets/) for review before writing any code. I have a draft of it ready.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Problem
Since #1355, specs can be nested (
specs/<domain>/<capability>/spec.md), which solves organisation. What is still missing is a way to say which specs belong together and at what version.Take an online shop whose store holds three kinds of specs:
These sets have different owners, audiences and release cadences. Each one needs to answer "what is in it, and which version is current?" Today OpenSpec has no concept for that:
config.yamlhasschema,contextandrules, but nothing about spec membership or versions..openspec.yamlcarriesschemaandcreated, not the version of the specs it touches.changes/archive/folders. They record changes, not a released state of a group of specs.Why a hand-written manifest is not enough
The obvious workaround is a manifest per group, next to the specs:
This works until the specs move. OpenSpec does not know about the file, so:
fulfilment/pickingtofulfilment/order-picking, or addfulfilment/click-and-collect, and the manifest is silently wrong. We saw most entries go stale after a single rename pass.versionto archiving a change, so the number goes stale too.list,show,validateandcontextignore the grouping.Proposal
Add first-class spec sets: a named, versioned group of specs, selected by path prefix instead of a file list.
1. Declaration
In
config.yaml:A per-set file (
specs/<name>.specset.yaml) with the same fields would also work. With prefix-based membership, adding or renaming a spec never means editing the manifest.2. Validation
openspec validate(anddoctor) should report:specSets.requireMembership: true);includeentry that matches nothing.3. CLI
openspec list --specsgroups output by set and shows each set's version.openspec list --specs --set fulfilmentandopenspec show --set compliancefilter by set.openspec contextincludes set names and versions in the agent brief.4. Versioning on archive
openspec archive <change>already knows which specs a change touched, so it knows the affected sets. It could:--bump patch|minor|major) or derived from the delta:REMOVEDrequirements give a major bump,ADDEDgives a minor bump, andMODIFIEDgives a patch bump;.openspec.yaml, so the archive shows which release each change landed in.For the example above, archiving a change that drops the "returns accepted without a receipt" requirement would say: "Fulfilment 3.2.0 → 4.0.0 (breaking: REMOVED requirement in fulfilment/returns)". The warehouse team would see that before merging, not after the new rule reaches the sites.
A plain "report only, bump by hand" first step would already be useful.
Why this fits OpenSpec
specSetsbehave exactly as today.explorations/workspace-architecture.md(Models B/D) and proposal: allow changes to be nested under a namespace folder #1917 (namespaced changes): a spec set is the release unit on top of namespaces.specSets: { fulfilment: ^3.0.0 }). That gives the drift and staleness signal discussed in that thread.Open questions
allset)?<set>-v<version>)?specSetsthe right name, orbundles/packages?If the direction is agreed, I'll follow up with an OpenSpec change proposal (
openspec/changes/add-spec-sets/) for review before writing any code. I have a draft of it ready.All reactions