Skip to content
Open
Show file tree
Hide file tree
Changes from 44 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
9f80a43
feat: add hierarchical spec structure support
lsmonki Feb 4, 2026
7d10cc2
fix: skip root-level spec.md in discovery and use recursive delta det…
lsmonki Feb 4, 2026
098fef8
fix: use path.join for cross-platform path separators
lsmonki Feb 4, 2026
70d74ba
refactor: remove duplicate SpecUpdate and rename Spec to DiscoveredSpec
lsmonki Feb 4, 2026
ab285b1
refactor: use isSpecStructureHierarchical utility and fix view.ts dis…
lsmonki Feb 4, 2026
18e9111
fix: deep-merge specStructure in global config and deduplicate orphan…
lsmonki Feb 4, 2026
8ea4d07
chore: remove unused imports and fix variable shadowing
lsmonki Feb 4, 2026
7a0c4bf
docs: add language tags to fenced blocks and fix invalid JSON
lsmonki Feb 4, 2026
36c3ed2
test: add findSpecUpdates tests, root-level edge case, and fix mislea…
lsmonki Feb 4, 2026
509bb52
feat: add specStructure to project-level config
lsmonki Feb 4, 2026
ed71300
fix: enforce structure and allowMixed in spec structure validation
lsmonki Feb 4, 2026
7b9a68f
chore: archive enforce-spec-structure-mode and sync delta specs
lsmonki Feb 4, 2026
2db4fbf
refactor: remove redundant Partial type and cast in project config pa…
lsmonki Feb 4, 2026
dc408b0
refactor: remove misleading async from findSpecUpdates wrapper
lsmonki Feb 4, 2026
1f14217
refactor: eliminate double findAllSpecs traversal in list and view
lsmonki Feb 4, 2026
77bd0a4
refactor: eliminate double findAllSpecs traversal in bulk validation
lsmonki Feb 4, 2026
8be039c
fix: validate specStructure sub-fields in global config
lsmonki Feb 4, 2026
a417a95
fix: move structure validation to separate field in bulk output
lsmonki Feb 4, 2026
c338e62
docs: remove unverified performance claim and update config scope in …
lsmonki Feb 4, 2026
d5e68ea
fix: use capability-path instead of capability-name in skill templates
lsmonki Feb 4, 2026
4e3ff09
fix: normalize path separators in validate direct item lookup
lsmonki Feb 4, 2026
6f95c63
fix: use update.capability instead of path.basename in delta error me…
lsmonki Feb 4, 2026
7b3ae53
style: remove extra leading space in config-schema doc comment
lsmonki Feb 4, 2026
a007ebe
refactor: remove redundant ZodError cast after instanceof check
lsmonki Feb 4, 2026
65b6508
fix: remove .gitignore from RESERVED_NAMES in spec structure validation
lsmonki Feb 4, 2026
4c08439
docs: add language tags to fenced code blocks missing them
lsmonki Feb 4, 2026
23780c5
refactor: reuse SpecStructureConfigSchema in global-config instead of…
lsmonki Feb 4, 2026
5fe2fef
refactor: remove unnecessary async from getSpecCapabilities
lsmonki Feb 4, 2026
6dc9b13
fix: handle empty path in Zod validation error messages
lsmonki Feb 4, 2026
e0aee8a
fix: align HARD_LIMIT_DEPTH with schema max of 10
lsmonki Feb 4, 2026
50fe584
docs: add language tags to fenced code blocks in spec and design files
lsmonki Feb 4, 2026
a59f8f8
test: add upper boundary test for maxDepth rejection in project config
lsmonki Feb 4, 2026
3f43394
refactor: sort directory entries in findAllSpecs for deterministic order
lsmonki Feb 4, 2026
4fb0d3e
refactor: remove redundant sorts now that findAllSpecs returns sorted…
lsmonki Feb 4, 2026
4fdc8c3
docs: fix incomplete sentence and vague phrasing in archived design doc
lsmonki Feb 4, 2026
94e6e36
fix: reject Windows reserved device names in spec path validation
lsmonki Feb 4, 2026
a97d7b5
feat: add path length validation for Windows MAX_PATH and capability …
lsmonki Feb 4, 2026
c71be16
fix: warn on unreadable delta spec files during archive validation
lsmonki Feb 6, 2026
ba4d1bc
fix: use recursive capability-path in delta spec discovery instructions
lsmonki Feb 6, 2026
e94b23a
fix: correct test name from maxDepth 0 to maxDepth 1
lsmonki Feb 6, 2026
38d0102
fix: relax view test ordering assertion for hierarchical specs
lsmonki Feb 6, 2026
a89684e
fix: correct view test description to match actual assertion
lsmonki Feb 6, 2026
6803720
fix: use path.join in change-parser test assertions for cross-platfor…
lsmonki Feb 6, 2026
1017e79
fix: use path.join for synthetic path fields in spec-discovery tests …
lsmonki Feb 6, 2026
3399695
fix: align design.md snippet with actual findAllSpecs implementation
lsmonki Feb 7, 2026
f39f65b
docs: clarify naming convention regex applies per path segment
lsmonki Feb 7, 2026
a6b7abb
docs: clarify path separator conventions for code vs documentation
lsmonki Feb 7, 2026
71fbbb1
fix: use path.sep instead of hardcoded / in reserved names test paths
lsmonki Feb 7, 2026
76bcaa3
fix: strengthen mixed specs assertion to check both auth and testing
lsmonki Feb 7, 2026
ec3e486
docs: update design.md detection algorithm to match final implementation
lsmonki Feb 7, 2026
0521eef
docs: align design.md depth limits, detection cost, and separator dec…
lsmonki Feb 7, 2026
d349790
docs: clarify separator strategy across layers in design.md
lsmonki Feb 7, 2026
9b38608
Merge branch 'main' into feature/hierarchical-specs-support
lsmonki Feb 7, 2026
611e650
docs: fix allowMixed non-goal inconsistency and resolve open question…
lsmonki Feb 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,6 @@ result
# OpenCode
.opencode/
opencode.json

# Codex
.codex/
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
# @fission-ai/openspec

## Unreleased

### Minor Changes

- **Hierarchical spec structures** — OpenSpec now supports organizing specifications in nested directory hierarchies (e.g., `_global/testing/`, `platform/services/api/`) alongside the traditional flat structure. Auto-detects structure, maintains full backward compatibility, and includes comprehensive migration guide.

**Features:**
- Recursive spec discovery with `findAllSpecs()` utility
- Auto-detection of flat vs. hierarchical structures
- Structure validation with configurable depth limits and naming conventions
- 1:1 delta replication (change deltas mirror main spec structure)
- Cross-platform path handling (Windows, macOS, Linux)
- Configuration via `specStructure` in global and project config

**Updated commands:**
- `list`, `validate`, `sync`, `archive` - all support hierarchical paths
- Change parser and validator use recursive discovery

**Documentation:**
- [Organizing Specs Guide](docs/organizing-specs.md)
- [Migration Guide](docs/migration-flat-to-hierarchical.md)
- [Troubleshooting](docs/troubleshooting-hierarchical-specs.md)
- [Example project](examples/hierarchical-specs/)

## 1.1.1

### Patch Changes
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ Now tell your AI: `/opsx:new <what-you-want-to-build>`
**[Supported Tools](docs/supported-tools.md)**: tool integrations & install paths<br>
**[Concepts](docs/concepts.md)**: how it all fits<br>
**[Multi-Language](docs/multi-language.md)**: multi-language support<br>
**[Customization](docs/customization.md)**: make it yours
**[Customization](docs/customization.md)**: make it yours<br>
**[Organizing Specs](docs/organizing-specs.md)**: flat vs hierarchical structures


## Why OpenSpec?
Expand Down
285 changes: 285 additions & 0 deletions docs/migration-flat-to-hierarchical.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,285 @@
# Migration Guide: Flat to Hierarchical Specs

This guide helps you migrate an existing OpenSpec project from flat to hierarchical spec organization.

## Should You Migrate?

**Consider migrating if:**
- You have 20+ specs that are hard to navigate
- Your specs naturally group by domain/subsystem
- Multiple teams own different spec areas
- You're working on a monorepo

**Stay flat if:**
- You have fewer than 20 specs
- Your project has a simple domain structure
- Your team prefers simplicity over organization

## Pre-Migration Checklist

Before starting, ensure:

1. ✓ All changes are archived (no active changes in `openspec/changes/`)
2. ✓ All specs are validated (`openspec validate --specs`)
3. ✓ You have a backup or version control
4. ✓ Your team agrees on the new structure

## Step 1: Plan Your Hierarchy

Design your new structure **before** moving files. Consider:

**Domain-based organization:**
```text
_global/ # Cross-cutting concerns
frontend/ # Frontend-specific specs
backend/ # Backend-specific specs
infrastructure/ # Infrastructure specs
```

**Subsystem-based organization:**
```text
platform/
services/
auth/
api/
database/
core/
business-logic/
data-models/
integrations/
payments/
notifications/
```

**Tips:**
- Use `_global/` for specs that apply everywhere (testing, security, monitoring)
- Group by team ownership when possible
- Keep depth reasonable (3-4 levels max)
- Use descriptive directory names (lowercase, hyphens)

## Step 2: Create Directory Structure

Create your new directory hierarchy:

```bash
# Example: Create _global and platform domains
mkdir -p openspec/specs/_global/{testing,security,monitoring}
mkdir -p openspec/specs/platform/services/{api,auth,database}
mkdir -p openspec/specs/platform/infrastructure/{deployment,scaling}
mkdir -p openspec/specs/frontend/{components,state-management}
```

## Step 3: Move Specs

Move each spec to its new location:

```bash
# Example: Move testing spec to _global
git mv openspec/specs/testing openspec/specs/_global/testing

# Example: Move api spec to platform/services
git mv openspec/specs/api openspec/specs/platform/services/api

# Continue for all specs...
```

**Important:** Use `git mv` if you're using git to preserve history.

## Step 4: Update References

### Update Change Proposals

If you have archived changes that reference old flat capability names, update their `proposal.md` files:

```markdown
<!-- Before -->
## Capabilities
- api
- auth
- database

<!-- After -->
## Capabilities
- platform/services/api
- platform/services/auth
- platform/services/database
```

### Update Documentation

Update any project documentation that references spec paths:

```markdown
<!-- Before -->
See specs/api/spec.md for API requirements

<!-- After -->
See specs/platform/services/api/spec.md for API requirements
```

## Step 5: Verify Migration

Run validations to ensure everything still works:

```bash
# Validate all specs
openspec validate --specs

# List all specs (verify new paths)
openspec list --specs

# View a hierarchical spec
openspec show _global/testing
openspec show platform/services/api
```

## Step 6: Update Configuration (Optional)

Update your global config to enforce hierarchical structure:

**~/.config/openspec/config.json** (Linux/macOS)
```json
{
"specStructure": {
"structure": "hierarchical",
"maxDepth": 4,
"allowMixed": false,
"validatePaths": true
}
}
```

**%APPDATA%/openspec/config.json** (Windows)

## Step 7: Communicate to Team

Inform your team about the new structure:

1. Share the new hierarchy diagram
2. Update your project README
3. Document naming conventions
4. Show examples of new change workflows

## Example Migration

### Before (Flat)
```text
openspec/specs/
auth/spec.md
api/spec.md
database/spec.md
testing/spec.md
security/spec.md
monitoring/spec.md
deployment/spec.md
```

### After (Hierarchical)
```text
openspec/specs/
_global/
testing/spec.md
security/spec.md
monitoring/spec.md
platform/
services/
api/spec.md
auth/spec.md
database/spec.md
infrastructure/
deployment/spec.md
```

### Commands After Migration

```bash
# Before
openspec show auth
openspec show testing

# After
openspec show platform/services/auth
openspec show _global/testing
```

## Creating New Changes After Migration

When creating new changes, use the hierarchical path:

```bash
# Before (flat)
/opsx:new add-oauth-support
# Creates: openspec/changes/add-oauth-support/specs/auth/spec.md

# After (hierarchical)
/opsx:new add-oauth-support
# Creates: openspec/changes/add-oauth-support/specs/platform/services/auth/spec.md
```

The change delta structure mirrors your main spec structure automatically.

## Gradual Migration

You can migrate gradually by mixing flat and hierarchical:

1. Start by moving specs to a few top-level domains
2. Keep remaining specs flat
3. Migrate more specs over time
4. Eventually enforce pure hierarchical with config

Example gradual migration:
```text
openspec/specs/
auth/spec.md # Still flat
payments/spec.md # Still flat
_global/
testing/spec.md # Migrated
security/spec.md # Migrated
platform/
services/
api/spec.md # Migrated
database/spec.md # Migrated
```

OpenSpec handles this mixed structure automatically.

## Rollback

If you need to rollback:

```bash
# Use git to revert the directory moves
git log --oneline # Find commit before migration
git reset --hard <commit-hash>

# Or manually move specs back
mv openspec/specs/_global/testing openspec/specs/testing
mv openspec/specs/platform/services/api openspec/specs/api
# Continue for all specs...
```

## Troubleshooting

### Spec not found after migration
**Problem:** `openspec show auth` returns "not found"

**Solution:** Use the full hierarchical path:
```bash
openspec show platform/services/auth
```

### Changes can't find specs
**Problem:** Old change references flat capability names

**Solution:** Update the change's proposal.md with new hierarchical names, or archive the change before migrating.

### Validation errors after migration
**Problem:** `openspec validate --specs` reports path errors

**Solution:** Ensure directory names follow conventions (lowercase, alphanumeric, hyphens/underscores only).

## Need Help?

- **Discord:** [Join the OpenSpec Discord](https://discord.gg/YctCnvvshC)
- **Issues:** [GitHub Issues](https://github.com/Fission-AI/OpenSpec/issues)
- **Docs:** [Organizing Specs](./organizing-specs.md)
Loading