|
| 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