Adds two change proposals for implementing Slice 3 of the artifact POC: 1. restructure-schema-directories - Move schemas from embedded TS objects to self-contained directories - Each schema becomes a directory with schema.yaml + templates/ - Enables co-located templates for user extensibility - 2-level resolution: user override → package built-in 2. add-instruction-loader (depends on #1) - Load templates from schema directories - Enrich templates with change context (dependencies, next steps) - Format change status for CLI output - New instruction-loader capability These proposals complete Slice 3 from docs/artifact_poc.md.
3.3 KiB
Context
Built-in schemas are currently embedded as TypeScript objects:
// src/core/artifact-graph/builtin-schemas.ts
export const SPEC_DRIVEN_SCHEMA: SchemaYaml = {
name: 'spec-driven',
version: 1,
artifacts: [...]
};
This doesn't support templates co-located with schemas. The instruction loader (Slice 3) needs templates, and the cleanest approach is self-contained schema directories.
Goals / Non-Goals
Goals:
- Schemas as self-contained directories (schema.yaml + templates/)
- User overrides via XDG data directory
- Simple 2-level resolution (user → package)
- Templates co-located with their schema
Non-Goals:
- Shared template fallback (intentionally avoiding complexity)
- Runtime schema compilation
- Schema inheritance
Decisions
1. Directory structure
Each schema is a directory containing schema.yaml and templates/:
<package>/schemas/
├── spec-driven/
│ ├── schema.yaml
│ └── templates/
│ ├── proposal.md
│ ├── design.md
│ ├── spec.md
│ └── tasks.md
└── tdd/
├── schema.yaml
└── templates/
├── spec.md
├── test.md
├── implementation.md
└── docs.md
Why: Self-contained like Helm charts. No cross-schema dependencies. Each schema owns its templates.
2. Resolution order (2 levels)
1. ${XDG_DATA_HOME}/openspec/schemas/<name>/schema.yaml # User override
2. <package>/schemas/<name>/schema.yaml # Built-in
3. Error (not found)
Why: Simple mental model. User can override entire schema directory or just parts.
3. Template path in schema.yaml
The template field is relative to the schema's templates/ directory:
# schemas/spec-driven/schema.yaml
artifacts:
- id: proposal
template: "proposal.md" # → schemas/spec-driven/templates/proposal.md
Why: Paths are relative to the schema, not a global templates directory.
4. Resolve package directory via import.meta.url
function getPackageSchemasDir(): string {
const currentFile = fileURLToPath(import.meta.url);
// Navigate from src/core/artifact-graph/ to package root
return path.join(path.dirname(currentFile), '..', '..', '..', 'schemas');
}
Why: Works in ESM. No hardcoded paths.
5. Keep schema.yaml format unchanged
The YAML format stays the same - only the storage location changes:
name: spec-driven
version: 1
description: Specification-driven development
artifacts:
- id: proposal
generates: "proposal.md"
template: "proposal.md"
requires: []
Why: No breaking changes to schema format. Just moving from TS to YAML files.
Migration
- Create
schemas/directory at package root - Convert
SPEC_DRIVEN_SCHEMAtoschemas/spec-driven/schema.yaml - Convert
TDD_SCHEMAtoschemas/tdd/schema.yaml - Update
resolveSchema()to load from directories - Remove
builtin-schemas.ts - Update
listSchemas()to scan directories
Risks / Trade-offs
File I/O at runtime:
- Previously schemas were in-memory objects
- Now requires reading YAML files
- Mitigation: Schemas are small, loaded once per operation
Package distribution:
- Must ensure
schemas/directory is included in npm package - Add to
filesin package.json
Open Questions
None.