6.3 KiB
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 allows a class to customize how an inherited slot behaves within that specific class context. It enables:
- Narrowing the
rangeto a more specific type - Adding class-specific
required,multivalued, oridentifierconstraints - Providing class-specific
description,examples, orpatternoverrides - 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:
# 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:
- Visual noise in the schema viewer (slot_usage badge displayed when nothing is actually customized)
- Maintenance burden (changes to generic slot must be mirrored in 374 files)
- 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:
- All properties match the generic slot definition exactly
- No additional properties are added (no extra
examples,description,required, etc.)
# 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):
# 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:
# 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:
linkml-validatepasses for all schemas- Generated RDF/OWL output is unchanged (redundant overrides have no semantic effect)
- Frontend slot viewer shows fewer
slot_usagebadges
Frontend UX Implications
The frontend LinkML viewer should:
- Display "Slot Usage" (with space, no underscore) instead of
slot_usage - Add tooltip explaining what slot_usage means, linking to LinkML documentation
- Only show badge when
slot_usagecontains meaningful modifications - 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
- 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 |