Class: Aidp::Metadata::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/aidp/metadata/parser.rb

Overview

Parses tool metadata from markdown files with YAML frontmatter

Extracts metadata headers from skill, persona, and template files. Supports both new metadata format and legacy skill format.

Examples:

Parsing a file

 = Parser.parse_file("/path/to/tool.md", type: "skill")

Parsing with auto-detection

 = Parser.parse_file("/path/to/SKILL.md")

Class Method Summary collapse

Class Method Details

.compute_file_hash(content) ⇒ String

Compute SHA256 hash of file content

Parameters:

  • content (String)

    File content

Returns:

  • (String)

    SHA256 hex string



82
83
84
# File 'lib/aidp/metadata/parser.rb', line 82

def self.compute_file_hash(content)
  Digest::SHA256.hexdigest(content)
end

.detect_type(file_path) ⇒ String

Detect tool type from file path

Parameters:

  • file_path (String)

    File path

Returns:

  • (String)

    Detected type (“skill”, “persona”, or “template”)



90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/aidp/metadata/parser.rb', line 90

def self.detect_type(file_path)
  case file_path
  when %r{/skills/}
    "skill"
  when %r{/personas/}
    "persona"
  when /SKILL\.md$/
    "skill"
  else
    "template"
  end
end

.parse_file(file_path, type: nil) ⇒ ToolMetadata

Parse metadata from a file

Parameters:

  • file_path (String)

    Path to .md file

  • type (String, nil) (defaults to: nil)

    Tool type (“skill”, “persona”, “template”) or nil to auto-detect

Returns:

Raises:



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/aidp/metadata/parser.rb', line 27

def self.parse_file(file_path, type: nil)
  Aidp.log_debug("metadata", "Parsing file", file: file_path, type: type)

  unless File.exist?(file_path)
    raise Aidp::Errors::ValidationError, "File not found: #{file_path}"
  end

  content = File.read(file_path, encoding: "UTF-8")
  file_hash = compute_file_hash(content)

  # Auto-detect type from filename or path if not specified
  type ||= detect_type(file_path)

  parse_string(content, source_path: file_path, file_hash: file_hash, type: type)
end

.parse_string(content, source_path:, file_hash:, type:) ⇒ ToolMetadata

Parse metadata from a string

Parameters:

  • content (String)

    File content with frontmatter

  • source_path (String)

    Source file path for reference

  • file_hash (String)

    SHA256 hash of content

  • type (String)

    Tool type (“skill”, “persona”, “template”)

Returns:

Raises:



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/aidp/metadata/parser.rb', line 51

def self.parse_string(content, source_path:, file_hash:, type:)
  , markdown = parse_frontmatter(content, source_path: source_path)

  # Map legacy skill fields to new metadata schema
  normalized = (, type: type)

  ToolMetadata.new(
    type: type,
    id: normalized["id"],
    title: normalized["title"],
    summary: normalized["summary"],
    version: normalized["version"],
    applies_to: normalized["applies_to"] || [],
    work_unit_types: normalized["work_unit_types"] || [],
    priority: normalized["priority"] || ToolMetadata::DEFAULT_PRIORITY,
    capabilities: normalized["capabilities"] || [],
    dependencies: normalized["dependencies"] || [],
    experimental: normalized["experimental"] || false,
    content: markdown,
    source_path: source_path,
    file_hash: file_hash
  )
rescue Aidp::Errors::ValidationError => e
  Aidp.log_error("metadata", "Metadata validation failed", error: e.message, file: source_path)
  raise
end