Skip to content

Commit aaf65a2

Browse files
authored
Merge branch 'main' into feature/bash_fish_power_shells_completions
2 parents 71f434b + c47cdaa commit aaf65a2

File tree

63 files changed

+4645
-359
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+4645
-359
lines changed

docs/artifact_poc.md

Lines changed: 36 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ Schemas can vary across multiple dimensions:
5252
Schemas follow the XDG Base Directory Specification with a 2-level resolution:
5353

5454
```
55-
1. ${XDG_DATA_HOME}/openspec/schemas/<name>.yaml # Global user override
56-
2. <package>/schemas/<name>.yaml # Built-in defaults
55+
1. ${XDG_DATA_HOME}/openspec/schemas/<name>/schema.yaml # Global user override
56+
2. <package>/schemas/<name>/schema.yaml # Built-in defaults
5757
```
5858

5959
**Platform-specific paths:**
@@ -69,25 +69,23 @@ Schemas follow the XDG Base Directory Specification with a 2-level resolution:
6969

7070
### Template Inheritance (2 Levels Max)
7171

72-
Templates also use 2-level resolution (to be implemented in Slice 3):
72+
Templates are co-located with schemas in a `templates/` subdirectory:
7373

7474
```
75-
1. ${XDG_DATA_HOME}/openspec/schemas/<schema>/templates/<artifact>.md # Schema-specific
76-
2. ${XDG_DATA_HOME}/openspec/templates/<artifact>.md # Shared
77-
3. <package>/templates/<artifact>.md # Built-in fallback
75+
1. ${XDG_DATA_HOME}/openspec/schemas/<schema>/templates/<artifact>.md # User override
76+
2. <package>/schemas/<schema>/templates/<artifact>.md # Built-in
7877
```
7978

8079
**Rules:**
81-
- Schema-specific templates override shared templates
82-
- Shared templates override package built-ins
80+
- User overrides take precedence over package built-ins
8381
- A CLI command shows resolved paths (no guessing)
8482
- No inheritance between schemas (copy if you need to diverge)
85-
- Max 2 levels - no deeper inheritance chains
83+
- Templates are always co-located with their schema
8684

8785
**Why this matters:**
8886
- Avoids "where does this come from?" debugging
8987
- No implicit magic that works until it doesn't
90-
- Clear boundaries between shared and specific
88+
- Schema + templates form a cohesive unit
9189

9290
---
9391

@@ -333,21 +331,19 @@ This separation means:
333331
### 3. XDG-Compliant Schema Resolution
334332

335333
```
336-
${XDG_DATA_HOME}/openspec/schemas/<name>.yaml # User override
334+
${XDG_DATA_HOME}/openspec/schemas/<name>/schema.yaml # User override
337335
↓ (not found)
338-
<package>/schemas/<name>.yaml # Built-in
336+
<package>/schemas/<name>/schema.yaml # Built-in
339337
↓ (not found)
340338
Error (schema not found)
341339
```
342340

343-
### 4. Two-Level Template Fallback (Slice 3)
341+
### 4. Two-Level Template Fallback
344342

345343
```
346-
${XDG_DATA_HOME}/openspec/schemas/<schema>/templates/<artifact>.md # Schema-specific
344+
${XDG_DATA_HOME}/openspec/schemas/<schema>/templates/<artifact>.md # User override
347345
↓ (not found)
348-
${XDG_DATA_HOME}/openspec/templates/<artifact>.md # Shared
349-
↓ (not found)
350-
<package>/templates/<artifact>.md # Built-in
346+
<package>/schemas/<schema>/templates/<artifact>.md # Built-in
351347
↓ (not found)
352348
Error (no silent fallback to avoid confusion)
353349
```
@@ -487,21 +483,29 @@ Structured as **vertical slices** - each slice is independently testable.
487483
# Global (XDG paths - user overrides)
488484
~/.local/share/openspec/ # Unix/macOS ($XDG_DATA_HOME/openspec/)
489485
%LOCALAPPDATA%/openspec/ # Windows
490-
├── schemas/ # Schema overrides
491-
│ └── custom-workflow.yaml # User-defined schema
492-
└── templates/ # Template overrides (Slice 3)
493-
└── proposal.md # Custom proposal template
486+
└── schemas/ # Schema overrides
487+
└── custom-workflow/ # User-defined schema directory
488+
├── schema.yaml # Schema definition
489+
└── templates/ # Co-located templates
490+
└── proposal.md
494491
495492
# Package (built-in defaults)
496493
<package>/
497-
├── schemas/ # Built-in schema definitions
498-
│ ├── spec-driven.yaml # Default: proposal → specs → design → tasks
499-
│ └── tdd.yaml # TDD: tests → implementation → docs
500-
└── templates/ # Built-in templates (Slice 3)
501-
├── proposal.md
502-
├── design.md
503-
├── specs.md
504-
└── tasks.md
494+
└── schemas/ # Built-in schema definitions
495+
├── spec-driven/ # Default: proposal → specs → design → tasks
496+
│ ├── schema.yaml
497+
│ └── templates/
498+
│ ├── proposal.md
499+
│ ├── design.md
500+
│ ├── spec.md
501+
│ └── tasks.md
502+
└── tdd/ # TDD: tests → implementation → docs
503+
├── schema.yaml
504+
└── templates/
505+
├── test.md
506+
├── implementation.md
507+
├── spec.md
508+
└── docs.md
505509
506510
# Project (change instances)
507511
openspec/
@@ -528,8 +532,8 @@ openspec/
528532
## Schema YAML Format
529533

530534
```yaml
531-
# Built-in: <package>/schemas/spec-driven.yaml
532-
# Or user override: ~/.local/share/openspec/schemas/spec-driven.yaml
535+
# Built-in: <package>/schemas/spec-driven/schema.yaml
536+
# Or user override: ~/.local/share/openspec/schemas/spec-driven/schema.yaml
533537
name: spec-driven
534538
version: 1
535539
description: Specification-driven development
@@ -538,7 +542,7 @@ artifacts:
538542
- id: proposal
539543
generates: "proposal.md"
540544
description: "Create project proposal document"
541-
template: "proposal.md" # resolves via 2-level fallback (Slice 3)
545+
template: "proposal.md" # resolves from co-located templates/ directory
542546
requires: []
543547

544548
- id: specs

docs/schema-customization.md

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
# Schema Customization
2+
3+
This document describes how users can customize OpenSpec schemas and templates, the current manual process, and the gap that needs to be addressed.
4+
5+
---
6+
7+
## Overview
8+
9+
OpenSpec uses a 2-level schema resolution system following the XDG Base Directory Specification:
10+
11+
1. **User override**: `${XDG_DATA_HOME}/openspec/schemas/<name>/`
12+
2. **Package built-in**: `<npm-package>/schemas/<name>/`
13+
14+
When a schema is requested (e.g., `spec-driven`), the resolver checks the user directory first. If found, that entire schema directory is used. Otherwise, it falls back to the package's built-in schema.
15+
16+
---
17+
18+
## Current Manual Process
19+
20+
To override the default `spec-driven` schema, a user must:
21+
22+
### 1. Determine the correct directory path
23+
24+
| Platform | Path |
25+
|----------|------|
26+
| macOS/Linux | `~/.local/share/openspec/schemas/` |
27+
| Windows | `%LOCALAPPDATA%\openspec\schemas\` |
28+
| All (if set) | `$XDG_DATA_HOME/openspec/schemas/` |
29+
30+
### 2. Create the directory structure
31+
32+
```bash
33+
# macOS/Linux example
34+
mkdir -p ~/.local/share/openspec/schemas/spec-driven/templates
35+
```
36+
37+
### 3. Find and copy the default schema files
38+
39+
The user must locate the installed npm package to copy the defaults:
40+
41+
```bash
42+
# Find the package location (varies by install method)
43+
npm list -g openspec --parseable
44+
# or
45+
which openspec && readlink -f $(which openspec)
46+
47+
# Copy files from the package's schemas/ directory
48+
cp <package-path>/schemas/spec-driven/schema.yaml ~/.local/share/openspec/schemas/spec-driven/
49+
cp <package-path>/schemas/spec-driven/templates/*.md ~/.local/share/openspec/schemas/spec-driven/templates/
50+
```
51+
52+
### 4. Modify the copied files
53+
54+
Edit `schema.yaml` to change the workflow structure:
55+
56+
```yaml
57+
name: spec-driven
58+
version: 1
59+
description: My custom workflow
60+
artifacts:
61+
- id: proposal
62+
generates: proposal.md
63+
description: Initial proposal
64+
template: proposal.md
65+
requires: []
66+
# Add, remove, or modify artifacts...
67+
```
68+
69+
Edit templates in `templates/` to customize the content guidance.
70+
71+
### 5. Verify the override is active
72+
73+
Currently there's no command to verify which schema is being used. Users must trust that the file exists in the right location.
74+
75+
---
76+
77+
## Gap Analysis
78+
79+
The current process has several friction points:
80+
81+
| Issue | Impact |
82+
|-------|--------|
83+
| **Path discovery** | Users must know XDG conventions and platform-specific paths |
84+
| **Package location** | Finding the npm package path varies by install method (global, local, pnpm, yarn, volta, etc.) |
85+
| **No scaffolding** | Users must manually create directories and copy files |
86+
| **No verification** | No way to confirm which schema is actually being resolved |
87+
| **No diffing** | When upgrading openspec, users can't see what changed in built-in templates |
88+
| **Full copy required** | Must copy entire schema even to change one template |
89+
90+
### User Stories Not Currently Supported
91+
92+
1. *"I want to add a `research` artifact before `proposal`"* — requires manual copy and edit
93+
2. *"I want to customize just the proposal template"* — must copy entire schema
94+
3. *"I want to see what the default schema looks like"* — must find package path
95+
4. *"I want to revert to defaults"* — must delete files and hope paths are correct
96+
5. *"I upgraded openspec, did the templates change?"* — no way to diff
97+
98+
---
99+
100+
## Proposed Solution: Schema Configurator
101+
102+
A CLI command (or set of commands) that handles path resolution and file operations for users.
103+
104+
### Option A: Single `openspec schema` command
105+
106+
```bash
107+
# List available schemas (built-in and user overrides)
108+
openspec schema list
109+
110+
# Show where a schema resolves from
111+
openspec schema which spec-driven
112+
# Output: /Users/me/.local/share/openspec/schemas/spec-driven/ (user override)
113+
# Output: /usr/local/lib/node_modules/openspec/schemas/spec-driven/ (built-in)
114+
115+
# Copy a built-in schema to user directory for customization
116+
openspec schema copy spec-driven
117+
# Creates ~/.local/share/openspec/schemas/spec-driven/ with all files
118+
119+
# Show diff between user override and built-in
120+
openspec schema diff spec-driven
121+
122+
# Remove user override (revert to built-in)
123+
openspec schema reset spec-driven
124+
125+
# Validate a schema
126+
openspec schema validate spec-driven
127+
```
128+
129+
### Option B: Dedicated `openspec customize` command
130+
131+
```bash
132+
# Interactive schema customization
133+
openspec customize
134+
# Prompts: Which schema? What do you want to change? etc.
135+
136+
# Copy and open for editing
137+
openspec customize spec-driven
138+
# Copies to user dir, prints path, optionally opens in $EDITOR
139+
```
140+
141+
### Option C: Init-time schema selection
142+
143+
```bash
144+
# During project init, offer schema customization
145+
openspec init
146+
# ? Select a workflow schema:
147+
# > spec-driven (default)
148+
# tdd
149+
# minimal
150+
# custom (copy and edit)
151+
```
152+
153+
### Recommended Approach
154+
155+
**Option A** provides the most flexibility and follows Unix conventions (subcommands for discrete operations). Key commands in priority order:
156+
157+
1. `openspec schema list` — see what's available
158+
2. `openspec schema which <name>` — debug resolution
159+
3. `openspec schema copy <name>` — scaffold customization
160+
4. `openspec schema diff <name>` — compare with built-in
161+
5. `openspec schema reset <name>` — revert to defaults
162+
163+
---
164+
165+
## Implementation Considerations
166+
167+
### Path Resolution
168+
169+
The resolver already exists in `src/core/artifact-graph/resolver.ts`:
170+
171+
```typescript
172+
export function getPackageSchemasDir(): string { ... }
173+
export function getUserSchemasDir(): string { ... }
174+
export function getSchemaDir(name: string): string | null { ... }
175+
export function listSchemas(): string[] { ... }
176+
```
177+
178+
New commands would leverage these existing functions.
179+
180+
### File Operations
181+
182+
- Copy should preserve file permissions
183+
- Copy should not overwrite existing user files without `--force`
184+
- Reset should prompt for confirmation
185+
186+
### Template-Only Overrides
187+
188+
A future enhancement could support overriding individual templates without copying the entire schema. This would require changes to the resolution logic:
189+
190+
```
191+
Current: schema dir (user) OR schema dir (built-in)
192+
Future: schema.yaml from user OR built-in
193+
+ each template from user OR built-in (independent fallback)
194+
```
195+
196+
This adds complexity but enables the "I just want to change one template" use case.
197+
198+
---
199+
200+
## Related Documents
201+
202+
- [Schema Workflow Gaps](./schema-workflow-gaps.md) — End-to-end workflow analysis and phased implementation plan
203+
204+
## Related Files
205+
206+
| File | Purpose |
207+
|------|---------|
208+
| `src/core/artifact-graph/resolver.ts` | Schema resolution logic |
209+
| `src/core/artifact-graph/instruction-loader.ts` | Template loading |
210+
| `src/core/global-config.ts` | XDG path helpers |
211+
| `schemas/spec-driven/` | Default schema and templates |

0 commit comments

Comments
 (0)