glam/.opencode/rules/linkml-yaml-best-practices-rule.md

3.6 KiB

LinkML YAML Best Practices Rule

Rule: Follow LinkML Conventions for Valid, Interoperable Schema Files

1. equals_expression Anti-Pattern

equals_expression is for dynamic formula evaluation (e.g., "{age_in_years} * 12"). Never use it for static value constraints.

WRONG:

slot_usage:
  has_type:
    equals_expression: '["hc:ArchiveOrganizationType"]'
  hold_record_set:
    equals_expression: '["hc:Fonds", "hc:Series"]'

CORRECT (single value):

slot_usage:
  has_type:
    equals_string: "hc:ArchiveOrganizationType"

CORRECT (multiple allowed values - if classes):

slot_usage:
  hold_record_set:
    any_of:
      - range: UniversityAdministrativeFonds
      - range: StudentRecordSeries
      - range: FacultyPaperCollection

CORRECT (multiple allowed values - if literals):

slot_usage:
  status:
    equals_string_in:
      - "active"
      - "inactive"
      - "pending"

2. Declare All Used Prefixes

Every CURIE prefix used in the file must be declared in the prefixes: block.

WRONG:

prefixes:
  linkml: https://w3id.org/linkml/
  skos: http://www.w3.org/2004/02/skos/core#
slot_usage:
  has_type:
    equals_string: "hc:ArchiveOrganizationType"  # hc: not declared!

CORRECT:

prefixes:
  linkml: https://w3id.org/linkml/
  hc: https://nde.nl/ontology/hc/
  skos: http://www.w3.org/2004/02/skos/core#
default_prefix: hc
slot_usage:
  has_type:
    equals_string: "hc:ArchiveOrganizationType"

3. Import Referenced Classes

When using external classes in is_a, range, or other references, import them.

WRONG:

imports:
  - linkml:types
classes:
  AcademicArchive:
    is_a: ArchiveOrganizationType      # Not imported!
    slot_usage:
      related_to:
        range: WikidataAlignment       # Not imported!

CORRECT:

imports:
  - linkml:types
  - ../classes/ArchiveOrganizationType
  - ../classes/WikidataAlignment
classes:
  AcademicArchive:
    is_a: ArchiveOrganizationType
    slot_usage:
      related_to:
        range: WikidataAlignment

4. Quote Regex Patterns and Annotation Values

Regex patterns:

# WRONG
pattern: ^Q[0-9]+$

# CORRECT
pattern: "^Q[0-9]+$"

Annotation values (must be strings):

# WRONG
annotations:
  specificity_score: 0.1

# CORRECT
annotations:
  specificity_score: "0.1"

5. Remove Unused Imports

Only import slots and classes that are actually used in the file.

WRONG:

imports:
  - ../slots/has_scope    # Never used in slots: or slot_usage:
  - ../slots/has_score
  - ../slots/has_type

CORRECT:

imports:
  - ../slots/has_score
  - ../slots/has_type

6. Slot Usage Requires Slot Presence

A slot referenced in slot_usage: must either be:

  • Listed in the slots: array, OR
  • Inherited from a parent class via is_a

WRONG:

classes:
  MyClass:
    slots:
      - has_type
    slot_usage:
      has_type: {...}
      identified_by: {...}    # Not in slots: and not inherited!

CORRECT:

classes:
  MyClass:
    slots:
      - has_type
      - identified_by
    slot_usage:
      has_type: {...}
      identified_by: {...}

Checklist for Class Files

  • All prefixes used in CURIEs are declared
  • default_prefix set if module belongs to that namespace
  • All referenced classes are imported
  • All used slots are imported
  • No equals_expression with static JSON arrays
  • Regex patterns are quoted
  • Annotation values are quoted strings
  • No unused imports
  • slot_usage only references slots that exist (via slots: or inheritance)