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

181 lines
3.6 KiB
Markdown

# 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:**
```yaml
slot_usage:
has_type:
equals_expression: '["hc:ArchiveOrganizationType"]'
hold_record_set:
equals_expression: '["hc:Fonds", "hc:Series"]'
```
**CORRECT** (single value):
```yaml
slot_usage:
has_type:
equals_string: "hc:ArchiveOrganizationType"
```
**CORRECT** (multiple allowed values - if classes):
```yaml
slot_usage:
hold_record_set:
any_of:
- range: UniversityAdministrativeFonds
- range: StudentRecordSeries
- range: FacultyPaperCollection
```
**CORRECT** (multiple allowed values - if literals):
```yaml
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:**
```yaml
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:**
```yaml
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:**
```yaml
imports:
- linkml:types
classes:
AcademicArchive:
is_a: ArchiveOrganizationType # Not imported!
slot_usage:
related_to:
range: WikidataAlignment # Not imported!
```
**CORRECT:**
```yaml
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:**
```yaml
# WRONG
pattern: ^Q[0-9]+$
# CORRECT
pattern: "^Q[0-9]+$"
```
**Annotation values (must be strings):**
```yaml
# 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:**
```yaml
imports:
- ../slots/has_scope # Never used in slots: or slot_usage:
- ../slots/has_score
- ../slots/has_type
```
**CORRECT:**
```yaml
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:**
```yaml
classes:
MyClass:
slots:
- has_type
slot_usage:
has_type: {...}
identified_by: {...} # Not in slots: and not inherited!
```
**CORRECT:**
```yaml
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)