Distilly Legacy Skill Compatibility: Handling Historic Skill Structures
Distilly maintains backward compatibility with legacy "colleague"-centric skill layouts through a layered approach that mirrors legacy fields, resolves both new and historic storage roots, and automatically generates compatibility metadata.
The titanwings/distilly repository implements a robust Distilly legacy skill compatibility system that allows modern skill definitions to coexist with historic directory structures and metadata formats. This architecture ensures that existing tooling, backup scripts, and CLI workflows continue to function without requiring manual migration of legacy assets.
Legacy-to-Canonical Field Mapping
The core compatibility shim resides in tools/skill_schema.py, where the sync_legacy_fields() function (lines 208–233) preserves backward compatibility by copying new schema values back into top-level legacy keys. This method ensures that fields like legacy_command, legacy_storage_root, and legacy_type remain populated even as the canonical schema evolves.
When processing skill metadata, Distilly automatically invokes this synchronization to maintain the original "colleague"-centric field structure that legacy tooling expects.
Automatic Compatibility Metadata Injection
After enriching a skill's metadata, the enrich_skill_meta() function injects a compat dictionary containing legacy identifiers (lines 222–226). This compatibility block is subsequently written to meta.json by the writer module.
The injection occurs automatically during the enrichment pipeline, ensuring that every skill—whether created through modern or legacy workflows—carries the necessary metadata for backward compatibility.
Preset-Based Legacy Value Management
Each character preset in tools/skill_presets.py declares specific legacy values that feed into the compatibility system:
- Colleague preset (lines 34–50): Uses legacy alias
/create-colleague, storage rootcolleagues, and typecolleague - Relationship preset (lines 61–77): Uses legacy alias
/create-ex, storage rootskills/relationship, and typerelationship - Celebrity preset (lines 84–90): Uses legacy alias
/create-icon, storage rootskills/celebrity, and typecelebrity
These preset definitions allow Distilly to automatically populate the compatibility block with the correct legacy identifiers based on the selected character type.
Resolving Historic Storage Paths
The resolve_existing_storage_root() function (lines 71–88) implements intelligent path resolution that bridges old and new directory structures. When locating an existing skill, the function first checks the canonical storage root; if the slug is not present there, it falls back to the legacy root path.
This transparent resolution enables the engine to address skills in both new canonical locations and historic "colleague" directories without requiring user configuration changes.
Version Management and Layout Preservation
The version manager in tools/version_manager.py (lines 5–7) explicitly maintains the legacy colleague layout during archive and restore operations. This ensures that older backup scripts and version control workflows continue to operate correctly, even as the underlying storage schema evolves.
Metadata Persistence
When writing artifacts, tools/skill_writer.py (lines 64–66) calls sync_legacy_fields() again during the meta.json serialization process. This double-synchronization ensures that the output file always contains the legacy keys required by external tooling, regardless of when the skill was originally created.
Practical Implementation Examples
The following examples demonstrate how to work with legacy compatibility features in Distilly:
# Enrich a raw legacy dict and obtain a compatibility block
from tools.skill_schema import enrich_skill_meta
legacy_meta = {
"name": "Old Colleague",
"character": "colleague", # legacy field
"tags": ["team", "project"], # legacy tags style
}
slug = "old-colleague"
full_meta = enrich_skill_meta(legacy_meta, slug)
print(full_meta["compat"])
# {'legacy_command': '/create-colleague',
# 'legacy_storage_root': 'colleagues',
# 'legacy_type': 'colleague', ...}
# Resolve a storage root that may be legacy or canonical
from tools.skill_presets import resolve_existing_storage_root
# Assume a skill lives under the old "colleagues/old-colleague" path
root = resolve_existing_storage_root("colleague", slug="old-colleague")
print(root) # -> Path('colleagues') if legacy exists, else Path('skills/colleague')
# CLI: Create a skill using a legacy-compatible command alias
distilly.mjs --action create \
--slug old-colleague \
--name "Old Colleague" \
--character colleague \
--work work.md \
--persona persona.md
# The generated meta.json will contain the `compat` block automatically.
Summary
- Field Mirroring:
sync_legacy_fields()intools/skill_schema.py(lines 208–233) copies modern schema values into legacy keys likelegacy_commandandlegacy_storage_root. - Metadata Injection: The
enrich_skill_meta()function automatically populates acompatdictionary (lines 222–226) that preserves legacy identifiers withinmeta.json. - Preset Definitions:
tools/skill_presets.py(lines 34–90) defines legacy aliases and storage roots for colleague, relationship, and celebrity character types. - Path Resolution:
resolve_existing_storage_root()(lines 71–88) implements fallback logic that checks canonical paths before defaulting to legacy directory structures. - Layout Preservation: The version manager maintains legacy colleague layouts during archival, while the skill writer ensures legacy fields persist in serialized metadata.
Frequently Asked Questions
How does Distilly handle storage path resolution for legacy skills?
When locating an existing skill, the resolve_existing_storage_root() function in tools/skill_presets.py first validates the canonical storage root. If the skill slug is absent from that location, the system automatically falls back to the legacy root directory defined by the character preset. This enables transparent access to both new and historic directory structures without requiring manual path configuration.
What specific legacy fields does Distilly preserve in skill metadata?
According to the source code in tools/skill_schema.py, Distilly preserves three critical legacy fields: legacy_command, legacy_storage_root, and legacy_type. These values are populated by sync_legacy_fields() and stored within a dedicated compat dictionary inside meta.json, ensuring that external tooling expecting the original "colleague"-centric schema remains functional.
Which character types support legacy compatibility aliases?
The tools/skill_presets.py file defines legacy compatibility for three distinct character presets. The colleague preset uses the /create-colleague alias, the relationship preset uses /create-ex, and the celebrity preset uses /create-icon. Each preset declares its specific legacy storage root and type identifier, enabling the framework to automatically generate appropriate compatibility metadata based on the selected character type.
Does Distilly require manual migration of existing legacy skills?
No manual migration is necessary. Distilly automatically detects and handles legacy skills through the fallback path resolution implemented in resolve_existing_storage_root(). Additionally, the enrich_skill_meta() function automatically generates compatibility metadata for existing assets, while the version manager preserves legacy layouts during backup and restore operations. This architecture ensures seamless interoperability between historic and modern skill definitions.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →