- 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
373 lines
12 KiB
Markdown
373 lines
12 KiB
Markdown
# Rule 53: Full Slot Migration - No Deprecation Notes
|
|
|
|
🚨 **CRITICAL**: When migrating slots from `slot_fixes.yaml`:
|
|
|
|
1. **Follow the `revision` section EXACTLY** - The `slot_fixes.yaml` file specifies the exact replacement slots and classes to use
|
|
2. **Perform FULL MIGRATION** - Completely remove the deprecated slot from the entity class
|
|
3. **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:
|
|
|
|
1. **Ontology analysis** - Each replacement was chosen based on alignment with base ontologies (CIDOC-CRM, RiC-O, PROV-O, Schema.org, etc.)
|
|
2. **Semantic correctness** - Revisions reflect the intended meaning of the original slot
|
|
3. **Pattern consistency** - Follows established naming conventions (Rule 39: RiC-O style, Rule 43: singular nouns)
|
|
4. **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 `revision` section TO THE LETTER
|
|
- ✅ Use EXACTLY the slots and classes specified
|
|
- ✅ Apply ALL components of the revision (both slots AND classes)
|
|
- ✅ Interpret `link_branch` fields correctly (see below)
|
|
- ✅ Update `processed.status: true` after 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
|
|
|
|
```yaml
|
|
- 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:
|
|
1. **Primary**: `has_or_had_quantity` slot → `Quantity` class
|
|
2. **Branch 1**: `Quantity.has_or_had_measurement_unit` → `MeasureUnit` (with value "visitors")
|
|
3. **Branch 2**: `Quantity.temporal_extent` → `TimeSpan`
|
|
|
|
### Resulting Class Structure
|
|
|
|
```yaml
|
|
# 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`
|
|
|
|
```yaml
|
|
- 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**:
|
|
1. **Primary**: `has_or_had_conversion_rate` → `ConversionRate`
|
|
2. **Branch 1**: Type hierarchy with `ConversionRateType` (abstract) + `ConversionRateTypes` (concrete subclasses)
|
|
3. **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
|
|
- [ ] 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**:
|
|
```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)
|
|
|
|
```yaml
|
|
# 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
|
|
|
|
```yaml
|
|
# 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`:
|
|
|
|
1. **Identify affected entity class(es)**
|
|
2. **Remove old slot from imports** (if dedicated import file exists)
|
|
3. **Remove old slot from slots list**
|
|
4. **Remove any slot_usage for old slot**
|
|
5. **Add new slot import** (if not already present)
|
|
6. **Add new slot to slots list**
|
|
7. **Add slot_usage for new slot** (if range override or customization needed)
|
|
8. **Update examples** to use new slot
|
|
9. **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):
|
|
```yaml
|
|
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):
|
|
```yaml
|
|
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:
|
|
|
|
```yaml
|
|
- 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**:
|
|
```yaml
|
|
- 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:
|
|
|
|
```yaml
|
|
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:
|
|
|
|
```yaml
|
|
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:
|
|
|
|
```yaml
|
|
# 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 `revision` section 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-lint` or `gen-owl`
|
|
- [ ] Updated `slot_fixes.yaml` with:
|
|
- `status: true`
|
|
- `timestamp` (ISO 8601)
|
|
- `session` identifier
|
|
- `notes` with "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.md`
|
|
- `schemas/20251121/linkml/modules/slots/slot_fixes.yaml` - **AUTHORITATIVE** master list of migrations
|