Skip to content

Openspec Folder Reader ​

Purpose ​

Read an openspec/ directory into a structured representation of specs, active changes, and archived changes.

Requirements ​

Requirement: Plugin reads the openspec folder and returns a structured representation ​

The function readOpenSpecFolder(dir: string): OpenSpecFolder SHALL scan the given directory and return a structured representation of all canonical specs, active changes, and archived changes.

Complete openspec folder
  • WHEN readOpenSpecFolder('./openspec') is called on a folder containing specs/ and changes/
  • THEN it returns an object with specs: CapabilitySpec[], changes: Change[], and archivedChanges: Change[]
Empty or missing folder
  • WHEN readOpenSpecFolder('./openspec') is called on a non-existent folder
  • THEN an error is thrown containing the folder path

Requirement: Canonical specs are read from openspec/specs/ ​

For each subdirectory in openspec/specs/ that contains a spec.md, a CapabilitySpec object SHALL be created with name (directory name) and specPath (absolute path to spec.md).

Multiple capabilities
  • WHEN openspec/specs/ contains directories nav-integration/ and sidebar-generation/, each with spec.md
  • THEN the result contains two CapabilitySpec entries with the correct names
Subdirectory without spec.md is ignored
  • WHEN a subdirectory in openspec/specs/ contains no spec.md
  • THEN it is not included in the result

Requirement: Changes are read with their artifacts ​

For each subdirectory in openspec/changes/ (except archive/) that contains a .openspec.yaml, a Change object SHALL be created with name, artifacts (which of proposal/design/tasks are present), and metadata from .openspec.yaml.

Change with all artifacts
  • WHEN openspec/changes/my-feature/ contains .openspec.yaml, proposal.md, design.md, tasks.md
  • THEN the Change object contains all three artifacts in artifacts
Change with missing design
  • WHEN openspec/changes/my-feature/ contains only .openspec.yaml and proposal.md
  • THEN artifacts contains only proposal

Requirement: Archived changes are read from changes/archive/ ​

Subdirectories in openspec/changes/archive/ SHALL be read as archived changes with the same fields as active changes, plus the date parsed from the directory name (YYYY-MM-DD-<name>).

Archived change
  • WHEN openspec/changes/archive/2026-03-10-my-feature/ exists with .openspec.yaml
  • THEN an archived Change object is created with archivedDate: '2026-03-10' and name: 'my-feature'

Requirement: title field from .openspec.yaml is read for changes ​

readOpenSpecFolder() MUST read an optional title field from .openspec.yaml and store it on the Change object as title?: string.

Change with title in .openspec.yaml
  • WHEN .openspec.yaml contains title: "OpenAPI v3 Migration"
  • THEN the Change object has title: 'OpenAPI v3 Migration'
Change without title field
  • WHEN .openspec.yaml does not contain a title field
  • THEN the Change object has title: undefined

Requirement: title frontmatter from spec.md is read for specs ​

readOpenSpecFolder() MUST parse the YAML frontmatter block of spec.md and extract an optional title field, storing it on the CapabilitySpec object as title?: string.

spec.md with frontmatter title
  • WHEN spec.md begins with ---\ntitle: "REST API Docs"\n---
  • THEN the CapabilitySpec object has title: 'REST API Docs'
spec.md without frontmatter
  • WHEN spec.md has no frontmatter block
  • THEN the CapabilitySpec object has title: undefined