From 74ec59c77c9d89e4ba1387627ed5c58a78422c49 Mon Sep 17 00:00:00 2001 From: Tabish Bidiwale Date: Mon, 19 Jan 2026 17:58:28 -0800 Subject: [PATCH 1/2] change(schema-management-cli): add proposal for schema management commands Propose new CLI commands to improve the UX of creating and managing project schemas: - `openspec schema init ` - Interactive wizard to scaffold new schemas - `openspec schema fork [name]` - Copy existing schema for customization - `openspec schema validate [name]` - Validate schema structure before runtime - `openspec schema which ` - Debug schema resolution path --- .../schema-management-cli/.openspec.yaml | 2 + .../changes/schema-management-cli/proposal.md | 55 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 openspec/changes/schema-management-cli/.openspec.yaml create mode 100644 openspec/changes/schema-management-cli/proposal.md diff --git a/openspec/changes/schema-management-cli/.openspec.yaml b/openspec/changes/schema-management-cli/.openspec.yaml new file mode 100644 index 00000000..749f7518 --- /dev/null +++ b/openspec/changes/schema-management-cli/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-01-20 diff --git a/openspec/changes/schema-management-cli/proposal.md b/openspec/changes/schema-management-cli/proposal.md new file mode 100644 index 00000000..efa2c092 --- /dev/null +++ b/openspec/changes/schema-management-cli/proposal.md @@ -0,0 +1,55 @@ +## Why + +Creating and managing project-local schemas currently requires manual directory creation, copying files, and hoping the structure is correct. Users only discover structural errors at runtime when commands fail. This friction discourages schema customization and makes it harder to tailor OpenSpec workflows to specific project needs. + +Key pain points: +- **Manual scaffolding**: Users must manually create `openspec/schemas//` with correct structure +- **No validation feedback**: Schema errors aren't caught until a command tries to use the schema +- **Starting from scratch is hard**: No easy way to base a custom schema on an existing one +- **Debugging resolution**: When a schema doesn't resolve as expected, there's no way to see the resolution path + +## What Changes + +Add a new `openspec schema` command group with subcommands for creating, forking, validating, and inspecting schemas. + +### Commands + +1. **`openspec schema init `** - Interactive wizard to scaffold a new project schema + - Prompts for schema description + - Prompts for artifacts to include (with explanations) + - Creates valid directory structure with `schema.yaml` and template files + - Optionally sets as project default in `openspec/config.yaml` + +2. **`openspec schema fork [name]`** - Copy an existing schema as a starting point + - Copies from user override or package built-in + - Allows renaming (defaults to `-custom`) + - Preserves all templates and configuration + +3. **`openspec schema validate [name]`** - Validate schema structure and templates + - Checks `schema.yaml` is valid + - Verifies all referenced templates exist + - Reports missing or malformed files + - Run without name to validate all project schemas + +4. **`openspec schema which `** - Show schema resolution path + - Displays which location the schema resolves from (project/user/package) + - Shows full path to schema directory + - Useful for debugging shadowing issues + +## Capabilities + +### New Capabilities +- `schema-init-command`: Interactive wizard for creating new project schemas with guided prompts +- `schema-fork-command`: Copy existing schemas to project for customization +- `schema-validate-command`: Validate schema structure and report errors before runtime +- `schema-which-command`: Debug schema resolution by showing which location is used + +### Modified Capabilities + + +## Impact + +- **Code**: New command implementations in `src/commands/` using existing resolver infrastructure +- **CLI**: New `schema` command group with 4 subcommands +- **Dependencies**: May use `enquirer` or similar for interactive prompts in `schema init` +- **Documentation**: Need to update CLI reference and schema customization guide From c87c41ddc8f7f869596b553443284a1d7721aa8c Mon Sep 17 00:00:00 2001 From: Tabish Bidiwale Date: Mon, 19 Jan 2026 18:17:12 -0800 Subject: [PATCH 2/2] change(schema-management-cli): add design, tasks, and specs artifacts Add implementation artifacts for the schema management CLI feature: - Design document with decisions and rationale - Task breakdown for implementation - Specs for schema init, fork, validate, and which commands --- .../changes/schema-management-cli/design.md | 113 ++++++++++++++++++ .../specs/schema-fork-command/spec.md | 66 ++++++++++ .../specs/schema-init-command/spec.md | 71 +++++++++++ .../specs/schema-validate-command/spec.md | 86 +++++++++++++ .../specs/schema-which-command/spec.md | 65 ++++++++++ .../changes/schema-management-cli/tasks.md | 67 +++++++++++ 6 files changed, 468 insertions(+) create mode 100644 openspec/changes/schema-management-cli/design.md create mode 100644 openspec/changes/schema-management-cli/specs/schema-fork-command/spec.md create mode 100644 openspec/changes/schema-management-cli/specs/schema-init-command/spec.md create mode 100644 openspec/changes/schema-management-cli/specs/schema-validate-command/spec.md create mode 100644 openspec/changes/schema-management-cli/specs/schema-which-command/spec.md create mode 100644 openspec/changes/schema-management-cli/tasks.md diff --git a/openspec/changes/schema-management-cli/design.md b/openspec/changes/schema-management-cli/design.md new file mode 100644 index 00000000..b7519e5d --- /dev/null +++ b/openspec/changes/schema-management-cli/design.md @@ -0,0 +1,113 @@ +## Context + +OpenSpec uses workflow schemas to define artifact sequences for change proposals. Currently, schemas are resolved from three locations (project → user → package), but managing custom schemas requires manual file creation with no tooling support. The resolver infrastructure exists (`src/core/artifact-graph/resolver.ts`) but there's no CLI exposure for schema management operations. + +Users who want to customize workflows must: +1. Manually create directory structures under `openspec/schemas//` +2. Copy and modify `schema.yaml` files without validation +3. Debug resolution issues by inspecting the filesystem directly + +This creates friction for schema customization and leads to runtime errors when schemas are malformed. + +## Goals / Non-Goals + +**Goals:** +- Provide CLI commands for common schema management operations +- Enable interactive schema creation with guided prompts +- Allow forking existing schemas as customization starting points +- Surface schema validation errors before runtime +- Help debug schema resolution order when shadowing occurs + +**Non-Goals:** +- Schema editing (users edit YAML directly or via `$EDITOR`) +- Schema publishing or sharing mechanisms +- Schema versioning or migration tooling +- Validation of template file contents (only checks existence) +- Schema inheritance or composition beyond simple forking + +## Decisions + +### 1. Command Structure: `openspec schema ` + +Add a new command group following the existing pattern used by `openspec config` and `openspec completion`. + +**Rationale:** Grouping related commands under a noun (schema) matches the established CLI patterns and provides a natural namespace for future schema operations. + +**Alternatives considered:** +- Flat commands (`openspec schema-init`, `openspec schema-fork`): Rejected because it pollutes the top-level namespace and doesn't scale well. +- Extending existing commands (`openspec init --schema`): Rejected because schema management is distinct from project initialization. + +### 2. Implementation Location + +New file `src/commands/schema.ts` with a `registerSchemaCommand(program: Command)` function that registers the `schema` command group and all subcommands. + +**Rationale:** Follows the pattern established by `config.ts` and matches how other command groups are organized. + +### 3. Schema Validation Approach + +Validation checks: +1. `schema.yaml` exists and is valid YAML +2. Parses successfully against the Zod schema in `types.ts` +3. All referenced template files exist in the schema directory +4. Artifact dependency graph has no cycles (use existing topological sort) + +**Rationale:** Reuse existing validation infrastructure (`parseSchema` from `schema.ts`) and extend with template existence checks. This catches the most common errors without duplicating validation logic. + +**Alternatives considered:** +- Deep template validation (check frontmatter, syntax): Rejected as over-engineering. Template contents are free-form markdown. + +### 4. Interactive Prompts for `schema init` + +Use `@inquirer/prompts` (already a dependency) for: +- Schema name input with kebab-case validation +- Schema description input +- Multi-select for artifact selection with descriptions +- Optional: set as project default + +**Rationale:** Matches the UX established by `openspec init` and `openspec config reset`. Provides a guided experience while keeping the wizard lightweight. + +### 5. Fork Source Resolution + +`schema fork ` resolves the source schema using the existing `getSchemaDir()` function, respecting the full resolution order (project → user → package). This allows forking from any accessible schema. + +The destination is always project-local: `openspec/schemas//` + +**Rationale:** Forking to project scope makes sense because: +- Custom schemas are project-specific decisions +- User-global schemas can be added manually if needed +- Keeps the command simple with a clear default + +### 6. Output Format Consistency + +All commands support `--json` flag for machine-readable output: +- `schema init`: Outputs `{ "created": true, "path": "...", "schema": "..." }` +- `schema fork`: Outputs `{ "forked": true, "source": "...", "destination": "..." }` +- `schema validate`: Outputs validation report matching existing validate command format +- `schema which`: Outputs `{ "name": "...", "source": "project|user|package", "path": "..." }` + +Text output uses ora spinners for progress and clear success/error messaging. + +**Rationale:** Consistent with existing OpenSpec commands and enables scripting/automation. + +### 7. Schema `which` Command Design + +Shows resolution details for a schema name: +- Which location it resolves from (project/user/package) +- Full path to the schema directory +- Whether it shadows other schemas at lower priority levels + +**Rationale:** Essential for debugging "why isn't my schema being used?" scenarios when multiple schemas with the same name exist. + +## Risks / Trade-offs + +**[Template scaffolding may become stale]** → The `schema init` command will scaffold a default set of artifacts (proposal, specs, design, tasks). If the built-in schema patterns evolve, these templates may not reflect best practices. +- *Mitigation*: Document that `init` creates a minimal starting point. Users can `fork` built-in schemas for the latest patterns. + +**[Interactive prompts in CI environments]** → `schema init` with prompts may hang in non-interactive environments. +- *Mitigation*: Support `--name`, `--description`, and `--artifacts` flags for non-interactive use. Detect TTY and show helpful error if prompts would hang. + +**[Validation doesn't catch all errors]** → Schema validation checks structure but can't verify semantic correctness (e.g., a template that doesn't match its artifact purpose). +- *Mitigation*: This is acceptable. Full semantic validation would require understanding template intent, which is out of scope. + +**[Fork overwrites without warning]** → If target schema already exists, `fork` could overwrite it. +- *Mitigation*: Check for existing schema and require `--force` flag or interactive confirmation before overwriting. diff --git a/openspec/changes/schema-management-cli/specs/schema-fork-command/spec.md b/openspec/changes/schema-management-cli/specs/schema-fork-command/spec.md new file mode 100644 index 00000000..3969b666 --- /dev/null +++ b/openspec/changes/schema-management-cli/specs/schema-fork-command/spec.md @@ -0,0 +1,66 @@ +## ADDED Requirements + +### Requirement: Schema fork copies existing schema +The CLI SHALL provide an `openspec schema fork [name]` command that copies an existing schema to the project's `openspec/schemas/` directory. + +#### Scenario: Fork with explicit name +- **WHEN** user runs `openspec schema fork spec-driven my-custom` +- **THEN** system locates `spec-driven` schema using resolution order (project → user → package) +- **AND** copies all files to `openspec/schemas/my-custom/` +- **AND** updates `name` field in `schema.yaml` to `my-custom` +- **AND** displays success message with source and destination paths + +#### Scenario: Fork with default name +- **WHEN** user runs `openspec schema fork spec-driven` without specifying a name +- **THEN** system copies to `openspec/schemas/spec-driven-custom/` +- **AND** updates `name` field in `schema.yaml` to `spec-driven-custom` + +#### Scenario: Source schema not found +- **WHEN** user runs `openspec schema fork nonexistent` +- **THEN** system displays error that schema was not found +- **AND** lists available schemas +- **AND** exits with non-zero code + +### Requirement: Schema fork prevents accidental overwrites +The CLI SHALL require confirmation or `--force` flag when the destination schema already exists. + +#### Scenario: Destination exists without force +- **WHEN** user runs `openspec schema fork spec-driven my-custom` and `openspec/schemas/my-custom/` exists +- **THEN** system displays error that destination already exists +- **AND** suggests using `--force` to overwrite +- **AND** exits with non-zero code + +#### Scenario: Destination exists with force flag +- **WHEN** user runs `openspec schema fork spec-driven my-custom --force` and destination exists +- **THEN** system removes existing destination directory +- **AND** copies source schema to destination +- **AND** displays success message + +#### Scenario: Interactive confirmation for overwrite +- **WHEN** user runs `openspec schema fork spec-driven my-custom` in interactive mode and destination exists +- **THEN** system prompts for confirmation to overwrite +- **AND** proceeds based on user response + +### Requirement: Schema fork preserves all schema files +The CLI SHALL copy the complete schema directory including templates, configuration, and any additional files. + +#### Scenario: Copy includes template files +- **WHEN** user forks a schema with template files (e.g., `proposal.md`, `design.md`) +- **THEN** all template files are copied to the destination +- **AND** template file contents are unchanged + +#### Scenario: Copy includes nested directories +- **WHEN** user forks a schema with nested directories (e.g., `templates/specs/`) +- **THEN** nested directory structure is preserved +- **AND** all nested files are copied + +### Requirement: Schema fork outputs JSON format +The CLI SHALL support `--json` flag for machine-readable output. + +#### Scenario: JSON output on success +- **WHEN** user runs `openspec schema fork spec-driven my-custom --json` +- **THEN** system outputs JSON with `forked: true`, `source`, `destination`, and `sourcePath` fields + +#### Scenario: JSON output shows source location +- **WHEN** user runs `openspec schema fork spec-driven --json` +- **THEN** JSON output includes `sourceLocation` field indicating "project", "user", or "package" diff --git a/openspec/changes/schema-management-cli/specs/schema-init-command/spec.md b/openspec/changes/schema-management-cli/specs/schema-init-command/spec.md new file mode 100644 index 00000000..8a811fca --- /dev/null +++ b/openspec/changes/schema-management-cli/specs/schema-init-command/spec.md @@ -0,0 +1,71 @@ +## ADDED Requirements + +### Requirement: Schema init command creates project-local schema +The CLI SHALL provide an `openspec schema init ` command that creates a new schema directory under `openspec/schemas//` with a valid `schema.yaml` file and default template files. + +#### Scenario: Create schema with valid name +- **WHEN** user runs `openspec schema init my-workflow` +- **THEN** system creates directory `openspec/schemas/my-workflow/` +- **AND** creates `schema.yaml` with name, version, description, and artifacts array +- **AND** creates template files referenced by artifacts +- **AND** displays success message with created path + +#### Scenario: Reject invalid schema name +- **WHEN** user runs `openspec schema init "My Workflow"` (contains space) +- **THEN** system displays error about invalid schema name +- **AND** suggests using kebab-case format +- **AND** exits with non-zero code + +#### Scenario: Schema name already exists +- **WHEN** user runs `openspec schema init existing-schema` and `openspec/schemas/existing-schema/` already exists +- **THEN** system displays error that schema already exists +- **AND** suggests using `--force` to overwrite or `schema fork` to copy +- **AND** exits with non-zero code + +### Requirement: Schema init supports interactive mode +The CLI SHALL prompt for schema configuration when run in an interactive terminal without explicit flags. + +#### Scenario: Interactive prompts for description +- **WHEN** user runs `openspec schema init my-workflow` in an interactive terminal +- **THEN** system prompts for schema description +- **AND** uses provided description in generated `schema.yaml` + +#### Scenario: Interactive prompts for artifact selection +- **WHEN** user runs `openspec schema init my-workflow` in an interactive terminal +- **THEN** system displays multi-select prompt with common artifacts (proposal, specs, design, tasks) +- **AND** each option includes a brief description +- **AND** uses selected artifacts in generated `schema.yaml` + +#### Scenario: Non-interactive mode with flags +- **WHEN** user runs `openspec schema init my-workflow --description "My workflow" --artifacts proposal,tasks` +- **THEN** system creates schema without prompting +- **AND** uses flag values for configuration + +### Requirement: Schema init supports setting project default +The CLI SHALL offer to set the newly created schema as the project default. + +#### Scenario: Set as default interactively +- **WHEN** user runs `openspec schema init my-workflow` in interactive mode +- **AND** user confirms setting as default +- **THEN** system updates `openspec/config.yaml` with `defaultSchema: my-workflow` + +#### Scenario: Set as default via flag +- **WHEN** user runs `openspec schema init my-workflow --default` +- **THEN** system creates schema and updates `openspec/config.yaml` with `defaultSchema: my-workflow` + +#### Scenario: Skip setting default +- **WHEN** user runs `openspec schema init my-workflow --no-default` +- **THEN** system creates schema without modifying `openspec/config.yaml` + +### Requirement: Schema init outputs JSON format +The CLI SHALL support `--json` flag for machine-readable output. + +#### Scenario: JSON output on success +- **WHEN** user runs `openspec schema init my-workflow --json --description "Test" --artifacts proposal` +- **THEN** system outputs JSON with `created: true`, `path`, and `schema` fields +- **AND** does not display interactive prompts or spinners + +#### Scenario: JSON output on error +- **WHEN** user runs `openspec schema init "invalid name" --json` +- **THEN** system outputs JSON with `error` field describing the issue +- **AND** exits with non-zero code diff --git a/openspec/changes/schema-management-cli/specs/schema-validate-command/spec.md b/openspec/changes/schema-management-cli/specs/schema-validate-command/spec.md new file mode 100644 index 00000000..977fdfac --- /dev/null +++ b/openspec/changes/schema-management-cli/specs/schema-validate-command/spec.md @@ -0,0 +1,86 @@ +## ADDED Requirements + +### Requirement: Schema validate checks schema structure +The CLI SHALL provide an `openspec schema validate [name]` command that validates schema configuration and reports errors. + +#### Scenario: Validate specific schema +- **WHEN** user runs `openspec schema validate my-workflow` +- **THEN** system locates schema using resolution order +- **AND** validates `schema.yaml` against the schema Zod type +- **AND** displays validation result (valid or list of errors) + +#### Scenario: Validate all project schemas +- **WHEN** user runs `openspec schema validate` without a name +- **THEN** system validates all schemas in `openspec/schemas/` +- **AND** displays results for each schema +- **AND** exits with non-zero code if any schema is invalid + +#### Scenario: Schema not found +- **WHEN** user runs `openspec schema validate nonexistent` +- **THEN** system displays error that schema was not found +- **AND** exits with non-zero code + +### Requirement: Schema validate checks YAML syntax +The CLI SHALL report YAML parsing errors with line numbers when possible. + +#### Scenario: Invalid YAML syntax +- **WHEN** user runs `openspec schema validate my-workflow` and `schema.yaml` has syntax errors +- **THEN** system displays YAML parse error with line number +- **AND** exits with non-zero code + +#### Scenario: Valid YAML but missing required fields +- **WHEN** `schema.yaml` is valid YAML but missing `name` field +- **THEN** system displays Zod validation error for missing required field +- **AND** identifies the specific missing field + +### Requirement: Schema validate checks template existence +The CLI SHALL verify that all template files referenced by artifacts exist. + +#### Scenario: Missing template file +- **WHEN** artifact references `template: proposal.md` but file doesn't exist in schema directory +- **THEN** system reports error: "Template file 'proposal.md' not found for artifact 'proposal'" +- **AND** exits with non-zero code + +#### Scenario: All templates exist +- **WHEN** all artifact templates exist +- **THEN** system reports that templates are valid +- **AND** template existence is included in validation summary + +### Requirement: Schema validate checks dependency graph +The CLI SHALL verify that artifact dependencies form a valid directed acyclic graph. + +#### Scenario: Valid dependency graph +- **WHEN** artifact dependencies form a valid DAG (e.g., tasks → specs → proposal) +- **THEN** system reports dependency graph is valid + +#### Scenario: Circular dependency detected +- **WHEN** artifact A requires B and artifact B requires A +- **THEN** system reports circular dependency error +- **AND** identifies the artifacts involved in the cycle +- **AND** exits with non-zero code + +#### Scenario: Unknown dependency reference +- **WHEN** artifact requires `nonexistent-artifact` +- **THEN** system reports error: "Artifact 'x' requires unknown artifact 'nonexistent-artifact'" +- **AND** exits with non-zero code + +### Requirement: Schema validate outputs JSON format +The CLI SHALL support `--json` flag for machine-readable validation results. + +#### Scenario: JSON output for valid schema +- **WHEN** user runs `openspec schema validate my-workflow --json` and schema is valid +- **THEN** system outputs JSON with `valid: true`, `name`, and `path` fields + +#### Scenario: JSON output for invalid schema +- **WHEN** user runs `openspec schema validate my-workflow --json` and schema has errors +- **THEN** system outputs JSON with `valid: false` and `issues` array +- **AND** each issue includes `level`, `path`, and `message` fields +- **AND** format matches existing `openspec validate` output structure + +### Requirement: Schema validate supports verbose mode +The CLI SHALL support `--verbose` flag for detailed validation information. + +#### Scenario: Verbose output shows all checks +- **WHEN** user runs `openspec schema validate my-workflow --verbose` +- **THEN** system displays each validation check as it runs +- **AND** shows pass/fail status for: YAML parsing, Zod validation, template existence, dependency graph diff --git a/openspec/changes/schema-management-cli/specs/schema-which-command/spec.md b/openspec/changes/schema-management-cli/specs/schema-which-command/spec.md new file mode 100644 index 00000000..3a3088bd --- /dev/null +++ b/openspec/changes/schema-management-cli/specs/schema-which-command/spec.md @@ -0,0 +1,65 @@ +## ADDED Requirements + +### Requirement: Schema which shows resolution result +The CLI SHALL provide an `openspec schema which ` command that displays where a schema resolves from. + +#### Scenario: Schema resolves from project +- **WHEN** user runs `openspec schema which my-workflow` and schema exists in `openspec/schemas/my-workflow/` +- **THEN** system displays source as "project" +- **AND** displays full path to schema directory + +#### Scenario: Schema resolves from user directory +- **WHEN** user runs `openspec schema which my-workflow` and schema exists only in user data directory +- **THEN** system displays source as "user" +- **AND** displays full path including XDG data directory + +#### Scenario: Schema resolves from package +- **WHEN** user runs `openspec schema which spec-driven` and no override exists +- **THEN** system displays source as "package" +- **AND** displays full path to package's schemas directory + +#### Scenario: Schema not found +- **WHEN** user runs `openspec schema which nonexistent` +- **THEN** system displays error that schema was not found +- **AND** lists available schemas +- **AND** exits with non-zero code + +### Requirement: Schema which shows shadowing information +The CLI SHALL indicate when a schema shadows another schema at a lower priority level. + +#### Scenario: Project schema shadows package +- **WHEN** user runs `openspec schema which spec-driven` and both project and package have `spec-driven` +- **THEN** system displays that project schema is active +- **AND** indicates it shadows the package version +- **AND** shows path to shadowed package schema + +#### Scenario: No shadowing +- **WHEN** schema exists only in one location +- **THEN** system does not display shadowing information + +#### Scenario: Multiple shadows +- **WHEN** project schema shadows both user and package schemas +- **THEN** system lists all shadowed locations in priority order + +### Requirement: Schema which outputs JSON format +The CLI SHALL support `--json` flag for machine-readable output. + +#### Scenario: JSON output basic +- **WHEN** user runs `openspec schema which spec-driven --json` +- **THEN** system outputs JSON with `name`, `source`, and `path` fields + +#### Scenario: JSON output with shadows +- **WHEN** user runs `openspec schema which spec-driven --json` and schema has shadows +- **THEN** JSON includes `shadows` array with `source` and `path` for each shadowed schema + +### Requirement: Schema which supports list mode +The CLI SHALL support listing all schemas with their resolution sources. + +#### Scenario: List all schemas +- **WHEN** user runs `openspec schema which --all` +- **THEN** system displays all available schemas grouped by source +- **AND** indicates which schemas shadow others + +#### Scenario: List in JSON format +- **WHEN** user runs `openspec schema which --all --json` +- **THEN** system outputs JSON array with resolution info for each schema diff --git a/openspec/changes/schema-management-cli/tasks.md b/openspec/changes/schema-management-cli/tasks.md new file mode 100644 index 00000000..390ed0ed --- /dev/null +++ b/openspec/changes/schema-management-cli/tasks.md @@ -0,0 +1,67 @@ +## 1. Setup and Command Structure + +- [ ] 1.1 Create `src/commands/schema.ts` with `registerSchemaCommand(program: Command)` function +- [ ] 1.2 Register schema command in `src/cli/index.ts` (import and call `registerSchemaCommand`) +- [ ] 1.3 Add schema command group with description: "Manage workflow schemas" + +## 2. Schema Which Command + +- [ ] 2.1 Add `schema which ` subcommand with `--json` and `--all` options +- [ ] 2.2 Implement resolution lookup using `getSchemaDir()` with project root +- [ ] 2.3 Implement shadow detection by checking all three locations (project, user, package) +- [ ] 2.4 Add text output: show source, path, and shadowing info +- [ ] 2.5 Add JSON output: `{ name, source, path, shadows: [] }` +- [ ] 2.6 Add `--all` mode to list all schemas with their resolution sources + +## 3. Schema Validate Command + +- [ ] 3.1 Add `schema validate [name]` subcommand with `--json` and `--verbose` options +- [ ] 3.2 Implement single-schema validation using existing `parseSchema()` from `schema.ts` +- [ ] 3.3 Add template existence check for each artifact's template file +- [ ] 3.4 Add dependency graph cycle detection (reuse topological sort logic) +- [ ] 3.5 Add validate-all mode when no name provided (scan `openspec/schemas/`) +- [ ] 3.6 Add text output with pass/fail indicators and error messages +- [ ] 3.7 Add JSON output matching existing `openspec validate` format: `{ valid, issues: [] }` +- [ ] 3.8 Add verbose mode showing each validation step + +## 4. Schema Fork Command + +- [ ] 4.1 Add `schema fork [name]` subcommand with `--json` and `--force` options +- [ ] 4.2 Implement source resolution using `getSchemaDir()` with project root +- [ ] 4.3 Implement default destination naming: `-custom` +- [ ] 4.4 Implement directory copy with recursive file copy +- [ ] 4.5 Update `name` field in copied `schema.yaml` +- [ ] 4.6 Add overwrite protection: check destination exists, require `--force` or confirmation +- [ ] 4.7 Add text output with source/destination paths +- [ ] 4.8 Add JSON output: `{ forked, source, destination, sourceLocation }` + +## 5. Schema Init Command + +- [ ] 5.1 Add `schema init ` subcommand with `--json`, `--description`, `--artifacts`, `--default`, `--no-default`, `--force` options +- [ ] 5.2 Implement schema name validation (kebab-case, no spaces) +- [ ] 5.3 Implement interactive prompts for description using `@inquirer/prompts` +- [ ] 5.4 Implement interactive artifact selection with descriptions (multi-select) +- [ ] 5.5 Create schema directory and `schema.yaml` with selected configuration +- [ ] 5.6 Create default template files for selected artifacts +- [ ] 5.7 Add `--default` flag to update `openspec/config.yaml` with new schema as default +- [ ] 5.8 Add overwrite protection: check if schema exists, require `--force` +- [ ] 5.9 Add text output with created path and next steps +- [ ] 5.10 Add JSON output: `{ created, path, schema }` +- [ ] 5.11 Add non-interactive mode with `--description` and `--artifacts` flags + +## 6. Testing + +- [ ] 6.1 Add unit tests for `schema which` command in `test/commands/schema.test.ts` +- [ ] 6.2 Add unit tests for `schema validate` command +- [ ] 6.3 Add unit tests for `schema fork` command +- [ ] 6.4 Add unit tests for `schema init` command +- [ ] 6.5 Test interactive mode mocking with `@inquirer/prompts` +- [ ] 6.6 Test JSON output format for all commands +- [ ] 6.7 Test error cases: invalid name, not found, already exists, cycle detection + +## 7. Documentation and Polish + +- [ ] 7.1 Add CLI help text for all schema subcommands +- [ ] 7.2 Update shell completion to include schema commands +- [ ] 7.3 Run linting and fix any issues (`npm run lint`) +- [ ] 7.4 Run full test suite (`npm test`)