# Distilly Legacy Skill Compatibility: Handling Historic Skill Structures

> Learn how Distilly ensures legacy skill compatibility by mirroring old fields, resolving storage roots, and auto-generating metadata. Maintain your historic skill structures seamlessly.

- Repository: [Tianyi Zhou/distilly](https://github.com/titanwings/distilly)
- Tags: how-to-guide
- Published: 2026-09-10

---

**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`](https://github.com/titanwings/distilly/blob/main/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`](https://github.com/titanwings/distilly/blob/main/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`](https://github.com/titanwings/distilly/blob/main/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 root `colleagues`, and type `colleague`
- **Relationship preset** (lines 61–77): Uses legacy alias `/create-ex`, storage root `skills/relationship`, and type `relationship`
- **Celebrity preset** (lines 84–90): Uses legacy alias `/create-icon`, storage root `skills/celebrity`, and type `celebrity`

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`](https://github.com/titanwings/distilly/blob/main/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`](https://github.com/titanwings/distilly/blob/main/tools/skill_writer.py)** (lines 64–66) calls **`sync_legacy_fields()`** again during the [`meta.json`](https://github.com/titanwings/distilly/blob/main/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:

```python

# 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', ...}

```

```python

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

```

```bash

# 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()` in [`tools/skill_schema.py`](https://github.com/titanwings/distilly/blob/main/tools/skill_schema.py) (lines 208–233) copies modern schema values into legacy keys like `legacy_command` and `legacy_storage_root`.
- **Metadata Injection**: The `enrich_skill_meta()` function automatically populates a `compat` dictionary (lines 222–226) that preserves legacy identifiers within [`meta.json`](https://github.com/titanwings/distilly/blob/main/meta.json).
- **Preset Definitions**: [`tools/skill_presets.py`](https://github.com/titanwings/distilly/blob/main/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`](https://github.com/titanwings/distilly/blob/main/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`](https://github.com/titanwings/distilly/blob/main/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`](https://github.com/titanwings/distilly/blob/main/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`](https://github.com/titanwings/distilly/blob/main/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.