# 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 |