Skip to content

[Proposal] Add hierarchical spec structure support #662

@lsmonki

Description

@lsmonki

Why

Working implementation: #660
Related to: #581

OpenSpec currently assumes a flat spec structure (specs/{capability}/spec.md) where each capability is a direct subdirectory under specs/. This works for simple projects but becomes limiting as projects grow. Teams need hierarchical organization for:

  • Domain-driven design: Grouping specs by bounded context (specs/payments/checkout/spec.md, specs/auth/oauth/spec.md)
  • Monorepos: Organizing specs by package or scope (specs/packages/core/spec.md)
  • Cross-cutting concerns: Separating global specs from feature-specific ones (specs/_global/testing/spec.md vs specs/features/export/spec.md)
  • Team namespaces: Large teams organizing specs by ownership (specs/team-platform/infra/spec.md)
  • Scale: Projects with 50+ specs become unmanageable in a flat structure

Commands like openspec list --specs, validation, sync, and archive fail to discover or work with hierarchically organized specs, forcing teams to use workarounds or manual processes.

What Changes

  • Core spec discovery: Implement recursive search for spec.md files at any depth, replacing the current single-level directory scan
  • Capability naming: Change capability identifier from directory name to full relative path from specs/ (e.g., _global/testing instead of just testing)
  • Delta mapping: Enable 1:1 path-based mapping between change deltas and main specs using replicated directory structure
  • Configuration: Add optional specStructure section in openspec/config.yaml or globally in ~/.config/openspec/config.json to control structure mode, depth limits, and validation behavior
    • structure: 'flat' | 'hierarchical' | 'auto' (default: auto - auto-detect)
    • maxDepth: Maximum hierarchy depth (default: 4, recommended: 2-3)
    • allowMixed: Allow mixing flat and hierarchical specs (default: true)
    • validatePaths: Enforce naming conventions (default: true)
  • Display: Update list and view commands to show hierarchical specs
  • Validation: Add validation rules to prevent orphaned specs (no spec.md at intermediate levels), enforce depth limits (warn at 4, hard limit at 10), and check naming conventions (lowercase alphanumeric with hyphens/underscores)
  • Backward compatibility: Auto-detect flat vs hierarchical structure and support both transparently
  • Templates: Update all skill prompts and templates to reference specs using relative paths
  • Commands: Adapt list, validate, sync, archive commands to work with hierarchical paths

Benefits:

  • Better organization: Group related specs by domain, team, or concern rather than forcing flat structure
  • Domain-driven design: Natural alignment with bounded contexts and domain models
  • Monorepo support: Organize specs by package, scope, or workspace
  • Scalability: Projects with 50+ specs remain navigable and maintainable
  • Team collaboration: Large teams can namespace their specs to avoid conflicts
  • Cross-cutting separation: Distinguish global concerns (_global/, shared/, utils/) from feature-specific specs
  • Code alignment: Spec structure can mirror code structure when beneficial
  • No workarounds: Eliminates need for custom schemas or hacks
  • Optional strictness: Configuration for validation during migrations or in large teams
  • Zero configuration: Works automatically with auto-detection, no setup required
  • Full compatibility: Existing flat projects continue working unchanged

Examples

Directory structures

Flat (current behavior):

openspec/specs/
  auth/spec.md
  api/spec.md
  payments/spec.md
  notifications/spec.md

Hierarchical (new):

openspec/specs/
  _global/
    testing/spec.md              # cross-cutting: testing standards
    security/spec.md             # cross-cutting: security requirements
    monitoring/spec.md           # cross-cutting: monitoring
  platform/
    services/
      api/spec.md                # service: API
      auth/spec.md               # service: authentication
      database/spec.md           # service: database
    infrastructure/
      deployment/spec.md         # infra: deployment
      scaling/spec.md            # infra: scaling
  frontend/
    components/
      forms/spec.md
      navigation/spec.md
    state-management/spec.md

Mixed (flat + hierarchical coexist):

openspec/specs/
  auth/spec.md                   # flat (depth 1)
  payments/spec.md               # flat (depth 1)
  _global/
    testing/spec.md              # hierarchical (depth 2)
    security/spec.md             # hierarchical (depth 2)
  platform/
    services/
      api/spec.md                # hierarchical (depth 3)

Change deltas mirror main structure 1:1

openspec/changes/add-rate-limiting/
  proposal.md
  specs/
    platform/
      services/
        api/spec.md              # delta for platform/services/api
    _global/
      security/spec.md           # delta for _global/security

CLI works with full paths

openspec validate platform/services/api    # validate a deep spec
openspec validate _global/testing          # validate a global spec
openspec validate --specs                  # validate all (auto-discovers)
openspec list --specs                      # list all with grouping

Output example (openspec list --specs)

Specs:
  _global/adr-workflow                  18 requirements
  _global/architecture                  12 requirements
  _global/testing                        8 requirements

  dev/mcp-server                        23 requirements
  dev/mcp-context-builder               14 requirements

  pel/expression-language                6 requirements

Configuration (optional, works without it)

In openspec/config.yaml:

specStructure:
  structure: auto        # auto | flat | hierarchical
  maxDepth: 4            # max nesting depth (1-10)
  allowMixed: true       # allow flat + hierarchical together
  validatePaths: true    # enforce naming conventions

Or globally in ~/.config/openspec/config.json:

{
  "specStructure": {
    "structure": "auto",
    "maxDepth": 4,
    "allowMixed": true,
    "validatePaths": true
  }
}

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