Skip to content

[Feature Request] Support nested capability paths in spec archive (e.g. specs/chats/my-chats/spec.md) #796

Closed

Description

@garlanddiego

Current behavior

The archive command applies delta specs by doing a shallow readdir of changes/<name>/specs/, mapping each direct subdirectory to openspec/specs/<capability>/spec.md. This only supports one level deep:

```
changes/my-change/specs/my-chats/spec.md → specs/my-chats/spec.md ✓
changes/my-change/specs/chats/my-chats/spec.md → specs/chats/my-chats/spec.md ✗ (skipped)
```

Relevant code in specs-apply.js > findSpecUpdates:
```js
const entries = await fs.readdir(changeSpecsDir, { withFileTypes: true });
for (const entry of entries) {
if (entry.isDirectory()) {
const specFile = path.join(changeSpecsDir, entry.name, "spec.md");
const targetFile = path.join(mainSpecsDir, entry.name, "spec.md");
```

Desired behavior

Support nested capability paths so delta specs can mirror a hierarchical product structure:

```
changes/my-change/specs/chats/my-chats/spec.md → specs/chats/my-chats/spec.md ✓
changes/my-change/specs/chats/group-setup/join-requirements/spec.md → specs/chats/group-setup/join-requirements/spec.md ✓
```

Use case

We organize main specs in openspec/specs/ as a nested tree mirroring our PRD structure (e.g. specs/chats/, specs/chats/my-chats/, specs/wallet-and-tx/orders/). We want delta specs in changes to follow the same structure, so archive can merge them to the right node.

Proposed fix

Make findSpecUpdates traverse recursively: find all spec.md files under changeSpecsDir, and map each one to the corresponding path under mainSpecsDir, preserving the relative path.

Activity

  1. changed the title [-]Support nested capability paths in spec archive (e.g. specs/chats/my-chats/spec.md)[/-] [+][Feature Request] Support nested capability paths in spec archive (e.g. specs/chats/my-chats/spec.md)[/+] on Mar 3, 2026
  2. clay-good commented on Jul 22, 2026

    @clay-good
    Collaborator

    Closing as fixed by #1355: delta spec discovery is recursive across parse, apply, and archive, so nested capability paths land where they belong.

    Verified on current main with your exact desired layout: a change with specs/chats/my-chats/spec.md archives cleanly and the requirement merges into openspec/specs/chats/my-chats/spec.md, not a flattened path. On main, ships with the next release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions