glam/.opencode/rules/linkml/slot-usage-minimization-rule.md
kempersc 6e63465196 Add ImageTilingServiceEndpoint class and archive ID class
- Introduced the ImageTilingServiceEndpoint class for tiled high-resolution image delivery, including deep-zoom and transformation capabilities, with multilingual descriptions and structured aliases.
- Archived the ID class as a backwards-compatible alias for Identifier, marking it as deprecated to enforce the use of the canonical Identifier model.
2026-02-15 21:40:13 +01:00

174 lines
6.3 KiB
Markdown

# Rule 49: Slot Usage Minimization - No Redundant Overrides
## Summary
LinkML `slot_usage` entries MUST provide meaningful modifications to the generic slot definition. Redundant `slot_usage` entries that merely re-declare the same values as the generic slot MUST be removed.
## Background
### What is slot_usage?
In LinkML, [`slot_usage`](https://linkml.io/linkml-model/latest/docs/slot_usage/) allows a class to customize how an inherited slot behaves within that specific class context. It enables:
- Narrowing the `range` to a more specific type
- Adding class-specific `required`, `multivalued`, or `identifier` constraints
- Providing class-specific `description`, `examples`, or `pattern` overrides
- Adding class-specific semantic mappings (`exact_mappings`, `close_mappings`, etc.)
### The Problem
A code generation process created **874 redundant `slot_usage` entries** across **374 class files** that simply re-declare the same `range` and `inlined` values already defined in the generic slot:
```yaml
# In modules/slots/template_specificity.yaml (GENERIC DEFINITION)
slots:
template_specificity:
slot_uri: hc:templateSpecificity
range: TemplateSpecificityScores
inlined: true
# In modules/classes/AdministrativeOffice.yaml (REDUNDANT OVERRIDE)
slot_usage:
template_specificity:
range: TemplateSpecificityScores # Same as generic!
inlined: true # Same as generic!
```
This creates:
1. **Visual noise** in the schema viewer (slot_usage badge displayed when nothing is actually customized)
2. **Maintenance burden** (changes to generic slot must be mirrored in 374 files)
3. **Semantic confusion** (suggests customization where none exists)
## The Rule
### MUST Remove: Truly Redundant Overrides
A `slot_usage` entry is **truly redundant** and MUST be removed if:
1. **All properties match the generic slot definition exactly**
2. **No additional properties are added** (no extra `examples`, `description`, `required`, etc.)
```yaml
# REDUNDANT - Remove this entire slot_usage entry
slot_usage:
template_specificity:
range: TemplateSpecificityScores
inlined: true
```
### MAY Keep: Description-Only Modifications
A `slot_usage` entry that ONLY modifies the `description` by adding articles or context MAY be kept if it provides **semantic value** by referring to a specific entity rather than a general concept.
**Tolerated Example** (adds definiteness):
```yaml
# Generic slot
slots:
has_or_had_record_set:
description: Record sets associated with a custodian.
range: RecordSet
# Class-specific slot_usage - TOLERABLE
slot_usage:
has_or_had_record_set:
description: The record sets held by this archive. # "The" makes it definite
```
**Rationale**: "The record sets" (definite) vs "record sets" (indefinite) conveys that this class specifically requires/expects record sets, rather than merely allowing them. This is a **semantic distinction** in linguistic terms (definiteness marking).
### MUST Keep: Meaningful Modifications
A `slot_usage` entry MUST be kept if it provides ANY of the following:
| Modification Type | Example |
|-------------------|---------|
| **Range narrowing** | `range: MuseumCollection` (from generic `Collection`) |
| **Required constraint** | `required: true` (when generic is optional) |
| **Pattern override** | `pattern: "^NL-.*"` (Dutch ISIL codes only) |
| **Examples addition** | Class-specific examples not in generic |
| **Inlined change** | `inlined: true` when generic is `false` |
| **Identifier designation** | `identifier: true` for primary key |
## Decision Matrix
| Scenario | Action |
|----------|--------|
| All properties match generic exactly | **REMOVE** |
| Only `range` and/or `inlined` match generic | **REMOVE** |
| Only `description` differs by adding articles | **TOLERATE** (but consider removing) |
| `description` provides substantive new information | **KEEP** |
| Any other property modified | **KEEP** |
## Implementation
### Cleanup Script
Use the following to identify and remove redundant overrides:
```python
# scripts/cleanup_redundant_slot_usage.py
import yaml
import glob
SLOTS_TO_CHECK = ['template_specificity', 'specificity_annotation']
for class_file in glob.glob('schemas/20251121/linkml/modules/classes/*.yaml'):
with open(class_file) as f:
content = yaml.safe_load(f)
modified = False
for cls_name, cls_def in content.get('classes', {}).items():
slot_usage = cls_def.get('slot_usage', {})
for slot_name in SLOTS_TO_CHECK:
if slot_name in slot_usage:
override = slot_usage[slot_name]
# Check if redundant (only range/inlined matching generic)
if is_redundant(override, slot_name):
del slot_usage[slot_name]
modified = True
# Remove empty slot_usage
if not slot_usage:
del cls_def['slot_usage']
if modified:
with open(class_file, 'w') as f:
yaml.dump(content, f, allow_unicode=True, sort_keys=False)
```
### Validation
After cleanup, validate that:
1. `linkml-validate` passes for all schemas
2. Generated RDF/OWL output is unchanged (redundant overrides have no semantic effect)
3. Frontend slot viewer shows fewer `slot_usage` badges
## Frontend UX Implications
The frontend LinkML viewer should:
1. **Display "Slot Usage"** (with space, no underscore) instead of `slot_usage`
2. **Add tooltip** explaining what slot_usage means, linking to [LinkML documentation](https://linkml.io/linkml-model/latest/docs/slot_usage/)
3. **Only show badge** when `slot_usage` contains meaningful modifications
4. **Comparison view** should highlight actual differences, not redundant re-declarations
## Affected Slots
Current analysis found redundant overrides for:
| Slot | Redundant Overrides | Files Affected |
|------|---------------------|----------------|
| `template_specificity` | 873 | 374 |
| `specificity_annotation` | 874 | 374 |
## References
- [LinkML slot_usage documentation](https://linkml.io/linkml-model/latest/docs/slot_usage/)
- Rule 38: Slot Centralization and Semantic URI Requirements
- Rule 48: Class Files Must Not Define Inline Slots
## Version History
| Date | Change |
|------|--------|
| 2026-01-12 | Initial rule created after identifying 874 redundant slot_usage entries |