- Document that slot_fixes.yaml revision section is authoritative - Add link_branch explanation for nested class attributes - Clarify that deprecated slots must be fully removed, not just annotated
12 KiB
Rule 53: Full Slot Migration - No Deprecation Notes
🚨 CRITICAL: When migrating slots from slot_fixes.yaml:
- Follow the
revisionsection EXACTLY - Theslot_fixes.yamlfile specifies the exact replacement slots and classes to use - Perform FULL MIGRATION - Completely remove the deprecated slot from the entity class
- Do NOT add deprecation notes - Never keep both old and new slots with deprecation markers
🚨 slot_fixes.yaml is AUTHORITATIVE AND CURATED 🚨
File Location: schemas/20251121/linkml/modules/slots/slot_fixes.yaml
THIS FILE IS THE SINGLE SOURCE OF TRUTH FOR ALL SLOT MIGRATIONS.
The slot_fixes.yaml file has been manually curated to specify the exact replacement slots and classes for each deprecated slot. The revisions are based on:
- Ontology analysis - Each replacement was chosen based on alignment with base ontologies (CIDOC-CRM, RiC-O, PROV-O, Schema.org, etc.)
- Semantic correctness - Revisions reflect the intended meaning of the original slot
- Pattern consistency - Follows established naming conventions (Rule 39: RiC-O style, Rule 43: singular nouns)
- Class hierarchy design - Type/Types pattern (Rule 0b) applied where appropriate
YOU MUST NOT:
- ❌ Substitute different slots than those specified in
revision - ❌ Use your own judgment to pick "similar" slots
- ❌ Skip the revision and invent new mappings
- ❌ Partially apply the revision (e.g., use the slot but not the class)
YOU MUST:
- ✅ Follow the
revisionsection TO THE LETTER - ✅ Use EXACTLY the slots and classes specified
- ✅ Apply ALL components of the revision (both slots AND classes)
- ✅ Interpret
link_branchfields correctly (see below) - ✅ Update
processed.status: trueafter completing migration
Understanding link_branch in Revision Plans
🚨 CRITICAL: The link_branch field in revision plans indicates nested class attributes. Items with link_branch: N are slots/classes that belong TO the primary class, not standalone replacements.
How to Interpret link_branch
| Revision Item | Meaning |
|---|---|
Items WITHOUT link_branch |
PRIMARY slot and class to create |
Items WITH link_branch: 1 |
First attribute branch that the primary class needs |
Items WITH link_branch: 2 |
Second attribute branch that the primary class needs |
Items WITH link_branch: N |
Nth attribute branch for the primary class |
Example: visitor_count Revision
- original_slot_id: https://nde.nl/ontology/hc/slot/visitor_count
revision:
- label: has_or_had_quantity # PRIMARY SLOT (no link_branch)
type: slot
- label: Quantity # PRIMARY CLASS (no link_branch)
type: class
- label: has_or_had_measurement_unit # Quantity needs this slot
type: slot
link_branch: 1 # ← Branch 1: unit attribute
- label: MeasureUnit # Range of has_or_had_measurement_unit
type: class
value:
- visitors
link_branch: 1
- label: temporal_extent # Quantity needs this slot too
type: slot
link_branch: 2 # ← Branch 2: time attribute
- label: TimeSpan # Range of temporal_extent
type: class
link_branch: 2
Interpretation: This creates:
- Primary:
has_or_had_quantityslot →Quantityclass - Branch 1:
Quantity.has_or_had_measurement_unit→MeasureUnit(with value "visitors") - Branch 2:
Quantity.temporal_extent→TimeSpan
Resulting Class Structure
# The Quantity class should have these slots:
Quantity:
slots:
- has_or_had_measurement_unit # From link_branch: 1
- temporal_extent # From link_branch: 2
Complex Example: visitor_conversion_rate
- original_slot_id: https://nde.nl/ontology/hc/slot/visitor_conversion_rate
revision:
- label: has_or_had_conversion_rate # PRIMARY SLOT
type: slot
- label: ConversionRate # PRIMARY CLASS
type: class
- label: has_or_had_type # ConversionRate.has_or_had_type
type: slot
link_branch: 1
- label: ConversionRateType # Abstract type class
type: class
link_branch: 1
- label: includes_or_included # ConversionRateType hierarchy slot
type: slot
link_branch: 1
- label: ConversionRateTypes # Concrete subclasses file
type: class
link_branch: 1
- label: temporal_extent # ConversionRate.temporal_extent
type: slot
link_branch: 2
- label: TimeSpan # Range of temporal_extent
type: class
link_branch: 2
Interpretation:
- Primary:
has_or_had_conversion_rate→ConversionRate - Branch 1: Type hierarchy with
ConversionRateType(abstract) +ConversionRateTypes(concrete subclasses) - Branch 2: Temporal tracking via
temporal_extent→TimeSpan
Migration Checklist for link_branch Revisions
- Create/verify PRIMARY slot exists
- Create/verify PRIMARY class exists
- For EACH
link_branch: N:- Add the branch slot to PRIMARY class's
slots:list - Import the branch slot file
- Import the branch class file (if creating new class)
- Verify range of branch slot points to branch class
- Add the branch slot to PRIMARY class's
- Update consuming class to use PRIMARY slot (not deprecated slot)
- Update examples to show nested structure
Mandatory: Follow slot_fixes.yaml Revisions Exactly
The revision section in slot_fixes.yaml is AUTHORITATIVE. Do not substitute different slots based on your own judgment.
Example from slot_fixes.yaml:
- original_slot_id: https://nde.nl/ontology/hc/slot/actual_start
revision:
- label: begin_of_the_begin # ← USE THIS SLOT
type: slot
- label: TimeSpan # ← USE THIS CLASS
type: class
CORRECT: Use begin_of_the_begin slot (as specified)
WRONG: Substitute has_actual_start_date (not in revision)
The Problem
Adding deprecation notes while keeping both old and new slots:
- Creates schema bloat with redundant properties
- Confuses data consumers about which slot to use
- Violates single-source-of-truth principle
- Complicates future data validation
Anti-Pattern (WRONG)
# WRONG - Keeping deprecated slot with deprecation note
classes:
TemporaryLocation:
slots:
- actual_start # OLD - kept with deprecation note
- actual_end # OLD - kept with deprecation note
- has_actual_start_date # NEW
- has_actual_end_date # NEW
slot_usage:
actual_start:
deprecated: |
DEPRECATED: Use has_actual_start_date instead.
# ... more deprecation documentation
Correct Pattern
# CORRECT - Only new slots, old slots completely removed
classes:
TemporaryLocation:
slots:
- has_actual_start_date # NEW - only new slots present
- has_actual_end_date # NEW
# NO slot_usage for deprecated slots - they don't exist in this class
Migration Steps
When processing a slot from slot_fixes.yaml:
- Identify affected entity class(es)
- Remove old slot from imports (if dedicated import file exists)
- Remove old slot from slots list
- Remove any slot_usage for old slot
- Add new slot import (if not already present)
- Add new slot to slots list
- Add slot_usage for new slot (if range override or customization needed)
- Update examples to use new slot
- Validate with gen-owl
What Happens to Old Slot Files
The old slot files in modules/slots/ (e.g., actual_start.yaml, activities_societies.yaml) are NOT deleted because:
- Other entity classes might still use them
- They serve as documentation of the old schema
- They can be archived when all usages are migrated
However, the old slots are removed from the entity class being migrated.
Example: TemporaryLocation Migration
Before (with old slots):
imports:
- ../slots/actual_end
- ../slots/actual_start
- ../slots/has_actual_start_date
- ../slots/has_actual_end_date
slots:
- actual_end
- actual_start
- has_actual_start_date
- has_actual_end_date
After (fully migrated):
imports:
# actual_end and actual_start imports REMOVED
- ../slots/has_actual_start_date
- ../slots/has_actual_end_date
slots:
# actual_end and actual_start REMOVED from list
- has_actual_start_date
- has_actual_end_date
Slot Usage for New Slots
Only add slot_usage for the new slot if you need to:
- Override the range for this specific class
- Add class-specific examples
- Add class-specific constraints
Do NOT add slot_usage just to document that it replaces an old slot.
Recording in slot_fixes.yaml
When marking a slot as processed:
- original_slot_id: https://nde.nl/ontology/hc/slot/actual_start
processed:
status: true
timestamp: '2026-01-14T16:00:00Z'
session: "session-2026-01-14-type-migration"
notes: "FULLY MIGRATED: TemporaryLocation - actual_start REMOVED, using temporal_extent with TimeSpan.begin_of_the_begin (Rule 53)"
Note the "FULLY MIGRATED" prefix in notes to confirm this was a complete removal, not a deprecation-in-place.
⚠️ Common Mistakes to Avoid ⚠️
Mistake 1: Substituting Different Slots
slot_fixes.yaml specifies:
- original_slot_id: https://nde.nl/ontology/hc/slot/actual_start
revision:
- label: begin_of_the_begin # ← MUST USE THIS
type: slot
- label: TimeSpan # ← WITH THIS CLASS
type: class
| Action | Status |
|---|---|
Using begin_of_the_begin with TimeSpan |
✅ CORRECT |
Using has_actual_start_date (invented) |
❌ WRONG |
Using start_date (different slot) |
❌ WRONG |
Using begin_of_the_begin WITHOUT TimeSpan |
❌ WRONG (incomplete) |
Mistake 2: Partial Application
The revision often specifies MULTIPLE components that work together:
revision:
- label: has_or_had_type # ← Slot for linking
type: slot
- label: BackupType # ← Abstract base class
type: class
- label: includes_or_included # ← Slot for hierarchy
type: slot
- label: BackupTypes # ← Concrete subclasses
type: class
All four components are part of the migration. Don't just use has_or_had_type and ignore the class structure.
Mistake 3: Using temporal_extent Slot Correctly
When slot_fixes.yaml specifies TimeSpan-based revision:
revision:
- label: begin_of_the_begin
type: slot
- label: TimeSpan
type: class
This means: Use the temporal_extent slot (which has range: TimeSpan) and access the temporal bounds via TimeSpan's slots:
# CORRECT: Use temporal_extent with TimeSpan structure
temporal_extent:
begin_of_the_begin: '2020-06-15'
end_of_the_end: '2022-03-15'
# WRONG: Create new has_actual_start_date slot
has_actual_start_date: '2020-06-15' # ❌ Not in revision!
Mistake 4: Not Updating Examples
When migrating slots, update ALL examples in the class file:
- Description examples (in class description)
- slot_usage examples
- Class-level examples (at bottom of file)
Verification Checklist
Before marking a slot as processed:
- Read the
revisionsection completely - Identified ALL slots and classes in revision
- Removed old slot from imports
- Removed old slot from slots list
- Removed old slot from slot_usage
- Added new slot(s) per revision
- Added new class import(s) per revision
- Updated ALL examples to use new slots
- Validated with
linkml-lintorgen-owl - Updated
slot_fixes.yamlwith:status: truetimestamp(ISO 8601)sessionidentifiernoteswith "FULLY MIGRATED:" prefix
See Also
- Rule 9: Enum-to-Class Promotion (single source of truth principle)
- Rule 0b: Type/Types File Naming Convention
- Rule 39: Slot Naming Convention (RiC-O Style)
.opencode/ENUM_TO_CLASS_PRINCIPLE.mdschemas/20251121/linkml/modules/slots/slot_fixes.yaml- AUTHORITATIVE master list of migrations