Skip to content
Back to skills

Skill Lifecycle Management

ASecurity

Manages the full lifecycle of OpenCode AI skills including versioning

  • 4 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added September 4, 2026
documentationpythongoazuretestingcode-reviewgitapisecuritydocumentation

Works with

  • api

Security analysis

A100/100

Scanned September 4, 2026

npx -y skills add paulpas/agent-skill-router --skill skill-lifecycle-management --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Skill Lifecycle Management?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Skill Lifecycle Management
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/paulpas-skill-lifecycle-management/badge)](https://www.skillsdirectory.com/skills/paulpas-skill-lifecycle-management)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---




name: skill-lifecycle-management
description: Manages the full lifecycle of OpenCode AI skills including versioning
  strategies, deprecation workflows, backward compatibility checks, and retirement
  procedures for the agent-skill-router system.
license: MIT
compatibility: opencode
metadata:
  version: "1.0.0"
  domain: agent
  triggers: skill lifecycle, versioning strategy, skill deprecation, backward compatibility,
    skill retirement, migration guide, how do i sunset a skill
  archetypes:
  - orchestration
  - strategic
  anti_triggers:
  - brainstorming
  - vague ideation
  - single-agent monolith
  response_profile:
    verbosity: medium
    directive_strength: high
    abstraction_level: tactical
  role: orchestration
  scope: orchestration
  output-format: analysis
  content-types:
  - guidance
  - examples
  - config
  - diagrams
  related-skills: skill-engineering, skill-router-system, skill-audit




---




# Skill Lifecycle Manager

Orchestrates the complete lifecycle of OpenCode AI skills from initial creation through versioning, deprecation, backward compatibility validation, and retirement — ensuring every skill evolves without breaking existing auto-routing pipelines.

## TL;DR Checklist

- [ ] Parse SKILL.md frontmatter and extract current version before any change
- [ ] Classify the change type (MAJOR / MINOR / PATCH) using semantic versioning rules
- [ ] Update `metadata.version` in frontmatter to match the classified bump
- [ ] Run backward compatibility check against all skills listing this one in `related-skills`
- [ ] If deprecating, write a migration guide and update related-skills cross-references
- [ ] Regenerate README catalog with `python3 scripts/generate_readme.py`

---

## When to Use

Use this skill when:

- You need to bump the version of an existing skill after making changes
- Planning to remove trigger terms, workflow steps, or frontmatter fields from a skill
- A skill has fallen out of use and needs deprecation or retirement procedures
- You are introducing a breaking change and need to communicate it to dependent skills
- Writing a migration guide for users affected by a skill's structural changes

---

## When NOT to Use

Avoid this skill for:

- Initial creation of a brand-new skill (use `skill-engineering` instead)
- Auditing the quality of existing skills (use `skill-audit` instead)
- Routing tasks to skills or managing the routing index itself (use `skill-router-system` instead)
- Simple typo fixes that do not change behavior — just commit with a PATCH version bump

---

## Core Workflow

```
┌──────────────┐    ┌───────────────┐    ┌───────────────┐
│   Idea       │    │   Design      │    │   Create      │
│   & Scope    │───▶│   Spec +     │───▶│   SKILL.md    │
│              │    │   Schema      │    │               │
└──────────────┘    └───────────────┘    └───────┬───────┘
                                                   │
┌──────────────┐    ┌───────────────┐    ┌─────────▼─────────┐
│   Retire     │◀───│  Deprecate    │◀───│   Deploy &        │
│   (archive)  │    │  (mark +      │    │   Validate        │
│              │    │   migrate)     │    │                   │
└──────────────┘    └───────────────┘    └─────────┬─────────┘
                                                   │
                                    ┌──────────────▼─────────┐
                                    │   Monitor &            │
                                    │   Version Bump         │
                                    └────────────────────────┘
```

1. **Classify the Change** — Determine whether the change to a skill is MAJOR, MINOR, or PATCH based on the semantic versioning rules below. Read the current `metadata.version` field, then decide the next version number.
   **Checkpoint:** Record the old version (e.g., `1.2.3`) and the new version (e.g., `1.3.0` for MINOR) in a changelog comment block at the top of SKILL.md.

2. **Bump the Version** — Edit the frontmatter `metadata.version` field to match the classified bump. Also increment the corresponding section count in the file (add/remove patterns, workflow steps).
   **Checkpoint:** Run `./scripts/validate_skill.sh <path>` to verify frontmatter is still valid YAML after the edit.

3. **Run Backward Compatibility Check** — Execute a cross-reference scan: find every other skill whose `related-skills` field lists this skill by name. Verify those skills' trigger sets will not break if this skill's triggers change.
   **Checkpoint:** No dependent skill should list a removed trigger term. If one does, either preserve the trigger or update the dependent skill first.

4. **Update Cross-References** — For every skill that lists this skill as related, verify the path is still correct (directory exists, frontmatter name matches). Remove any entries pointing to archived skills.
   **Checkpoint:** `grep -r "name: <this-skill>" skills/*/SKILL.md` should return only active skills with correct paths.

5. **Regenerate Documentation** — Run `python3 scripts/generate_readme.py` so the README skill catalog reflects any renamed, deprecated, or newly versioned entries.
   **Checkpoint:** Verify your skill appears in the README under its domain section with the updated description and version note.

6. **Commit With Version Tag** — Create a commit that includes only the version bump and any dependency updates: `git add skills/<domain>/<topic>/SKILL.md scripts/generate_readme.py`. Do not include unrelated changes in a version-only commit.
   **Checkpoint:** `git diff --cached` should show no unexpected files beyond the skill itself and the generated README.

---

## Implementation Patterns

### Versioning Strategy — Semantic Versioning Rules

Apply semantic versioning (MAJOR.MINOR.PATCH) to every skill. The rules are strict: a MAJOR bump means breaking changes, MINOR means additive changes, PATCH means non-functional edits.

```python
from enum import Enum


class VersionBumpType(Enum):
    MAJOR = "major"
    MINOR = "minor"
    PATCH = "patch"


def classify_version_bump(
    old_version: str,
    change_type: str
) -> tuple[str, str]:
    """Classify a version bump and compute the next version string.

    Args:
        old_version: Current semantic version (e.g., "1.2.3").
        change_type: One of 'major', 'minor', or 'patch'.

    Returns:
        Tuple of (bump_classification, new_version_string).

    Raises:
        ValueError: If old_version is not a valid semver string
                    or change_type is not one of the allowed values.
    """
    parts = old_version.split(".")
    if len(parts) != 3:
        raise ValueError(
            f"Expected semver format MAJOR.MINOR.PATCH, got: {old_version}"
        )

    try:
        major, minor, patch = [int(p) for p in parts]
    except ValueError:
        raise ValueError(f"Version parts must be integers: {old_version}")

    if change_type == "major":
        new_version = f"{major + 1}.0.0"
    elif change_type == "minor":
        new_version = f"{major}.{minor + 1}.0"
    elif change_type == "patch":
        new_version = f"{major}.{minor}.{patch + 1}"
    else:
        raise ValueError(
            f"Invalid change_type '{change_type}'. Use 'major', 'minor', or 'patch'."
        )

    return (change_type, new_version)


# Examples of classification:
# classify_version_bump("1.2.3", "patch") → ("patch", "1.2.4")
# classify_version_bump("1.2.3", "minor") → ("minor", "1.3.0")
# classify_version_bump("1.2.3", "major") → ("major", "2.0.0")
```

**Rules for classification:**

| Bump Type | What Changes | Example Scenario |
|-----------|-------------|-----------------|
| MAJOR | Trigger set changed, core workflow steps removed or reordered, frontmatter schema changed | Removing `stop loss` as a trigger after migrating to a new skill |
| MINOR | New patterns added, expanded examples, additional trigger terms, new sub-sections | Adding an ATR-based stop pattern to the existing stop-loss skill |
| PATCH | Typo fixes in prose, minor wording clarifications, code comment updates | Fixing a misspelled variable name in a docstring |

---

### Deprecation Workflow

When a skill should no longer be actively developed but must remain available for existing auto-routing:

```python
import os
import re
from dataclasses import dataclass


@dataclass
class DeprecationRecord:
    """Records the metadata of a deprecation event."""
    skill_name: str
    deprecated_by: str
    reason: str
    replacement_skill: str | None
    effective_date: str  # ISO 8601: "2026-05-19"
    sunset_date: str | None  # Optional future date for full retirement


def mark_deprecated(skill_path: str, record: DeprecationRecord) -> list[str]:
    """Mark a skill as deprecated by updating SKILL.md in place.

    Returns a list of file paths that were modified (includes cross-refs).

    Args:
        skill_path: Absolute path to the SKILL.md to deprecate.
        record: DeprecationRecord with full context.
    """
    with open(skill_path, "r") as f:
        content = f.read()

    lines = content.splitlines(True)

    # Insert DEPRECATED banner after H1 title
    modified = []
    for i, line in enumerate(lines):
        if line.startswith("# ") and not line.startswith("##"):
            modified.append(line)  # Keep the H1
            modified.append(f"\n<!-- ⚠️ DEPRECATED: {record.reason} -->\n")
            modified.append(
                f"<!-- Replaced by: `{record.replacement_skill}` -->\n"
            )
            modified.append("<!-- Deprecated: " + record.effective_date + " -->\n")
            continue
        modified.append(line)

    new_content = "".join(modified)

    # Verify the deprecation banner was inserted
    if "⚠️ DEPRECATED" not in new_content:
        raise RuntimeError("Failed to insert deprecation banner into SKILL.md")

    with open(skill_path, "w") as f:
        f.write(new_content)

    modified_files = [skill_path]

    # Update any related-skills entries that point here
    for skill_file in _find_related_skills(skill_path):
        updated = _update_related_reference(skill_file, record.replacement_skill)
        if updated:
            modified_files.append(skill_file)

    return modified_files


def write_migration_guide(
    deprecated_skill: str,
    replacement_skill: str,
    output_dir: str
) -> str:
    """Write a migration guide for users affected by the deprecation.

    Returns the path to the generated migration guide file.
    """
    guide_path = os.path.join(output_dir, f"migration-{deprecated_skill}.md")

    with open(guide_path, "w") as f:
        f.write(f"# Migration Guide: {deprecated_skill} → {replacement_skill}\n\n")
        f.write("## Why This Change Happened\n\n")
        f.write("This skill was deprecated because its functionality has been\n")
        f.write("consolidated into a newer, more comprehensive skill.\n\n")
        f.write("## What Changes for You\n\n")
        f.write(f"1. Replace any `{deprecated_skill}` trigger references with\n")
        f.write(f"   `{replacement_skill}` triggers.\n")
        f.write(f"2. Update your `related-skills` field to point to\n")
        f.write(f"   `{replacement_skill}` instead of `{deprecated_skill}`.\n")
        f.write(f"3. Review the [SKILL.md for {replacement_skill}]({replacement_skill}/SKILL.md)\n")
        f.write(f"   for updated workflow steps.\n\n")
        f.write("## Timeline\n\n")
        f.write("- **Today:** Skill marked deprecated, auto-routing still active\n")
        f.write("- **30 days:** Auto-routing gradually shifts to replacement skill\n")
        f.write("- **90 days:** Deprecated skill removed from skills-index.json\n")

    return guide_path


def _find_related_skills(current_skill_path: str) -> list[str]:
    """Find all SKILL.md files that reference the given skill in related-skills."""
    base_dir = os.path.dirname(os.path.dirname(os.path.dirname(current_skill_path)))
    results = []

    for domain_dir in os.listdir(base_dir):
        domain_path = os.path.join(base_dir, domain_dir)
        if not os.path.isdir(domain_path):
            continue
        for skill_dir in os.listdir(domain_path):
            skill_file = os.path.join(domain_path, skill_dir, "SKILL.md")
            if not os.path.isfile(skill_file):
                continue
            with open(skill_file, "r") as f:
                content = f.read()
            # Check for the skill name in related-skills field
            if f"{current_skill_path.split('/')[-2]}" in content:
                results.append(skill_file)

    return results


def _update_related_reference(
    skill_file: str, replacement_skill: str | None
) -> bool:
    """Update a cross-reference to point to the replacement skill."""
    with open(skill_file, "r") as f:
        content = f.read()

    # Simple replacement of related-skills entries
    old_name = skill_file.split("/")[-2]
    new_content = content.replace(old_name, replacement_skill or old_name)

    if old_name != (replacement_skill or ""):
        with open(skill_file, "w") as f:
            f.write(new_content)
        return True

    return False
```

---

### Backward Compatibility Checker

Before publishing a version change, verify that no dependent skills break. This function scans the entire skills directory for cross-reference integrity.

```python
import yaml


def check_backward_compatibility(skill_path: str, base_dir: str) -> dict:
    """Check backward compatibility before publishing a skill change.

    Args:
        skill_path: Path to the SKILL.md being modified.
        base_dir: Root directory of the skills/ folder.

    Returns:
        Compatibility report with issues and recommendations.
    {
        "compatible": True,
        "issues": [],
        "recommendations": []
    }
    """
    report = {"compatible": True, "issues": [], "recommendations": []}

    with open(skill_path, "r") as f:
        data = yaml.safe_load(f)

    old_triggers = set(
        t.strip()
        for t in data.get("metadata", {}).get("triggers", "").split(",")
    )
    skill_name = data["name"]

    # Scan all other skills for references to this one
    for root, dirs, files in os.walk(base_dir):
        if "SKILL.md" not in files:
            continue
        other_path = os.path.join(root, "SKILL.md")
        if other_path == skill_path:
            continue

        with open(other_path, "r") as f:
            other_data = yaml.safe_load(f)

        related = [
            s.strip()
            for s in (other_data.get("metadata", {}).get("related-skills") or "").split(",")
        ]

        if skill_name not in related:
            continue

        # This skill lists us as related — verify no trigger overlap issues
        other_triggers = set(
            t.strip()
            for t in (other_data.get("metadata", {}).get("triggers") or "").split(",")
        )

        # If we removed a trigger that the other skill uses
        removed_triggers = old_triggers - new_triggers  # type: ignore[name-defined]
        if removed_triggers & other_triggers:
            report["compatible"] = False
            report["issues"].append(
                f"Trigger(s) {removed_triggers} were removed but "
                f"'{other_data['name']}' still uses them."
            )
            report["recommendations"].append(
                f"Add back '{', '.join(removed_triggers)}' as a trigger or "
                f"update '{other_data['name']}' to use the replacement skill."
            )

    return report


# Usage example:
# report = check_backward_compatibility("skills/trading/risk-stop-loss/SKILL.md", "skills/")
# if not report["compatible"]:
#     for issue in report["issues"]:
#         print(f"ISSUE: {issue}")
#     for rec in report["recommendations"]:
#         print(f"FIX: {rec}")
```

---

### Retirement and Sunset Procedure

When a skill reaches end-of-life, follow this archive procedure:

```yaml
# Step 1: Move to .archive/ directory structure
# skills/ -> .archive/skills/<domain>/<topic>/
# Preserve the original SKILL.md with DEPRECATED banner intact

# Step 2: Update skills-index.json
# - Remove the skill from the active index
# - Add an "archived" entry under a new "archived_skills" array
#   {
#     "name": "old-skill-name",
#     "domain": "agent",
#     "archived_date": "2026-05-19",
#     "replaced_by": "new-skill-name",
#     "reason": "functionality superseded by new skill"
#   }

# Step 3: Update README.md catalog
# - Remove from the active skill count per domain
# - Add a small "Archived Skills" section at the bottom with links to .archive/

# Step 4: Verify dependent skills no longer reference the archived one
```

**When to retire a skill:**
- **Low usage** — The router access log shows fewer than 10 matches per month for 6 consecutive months
- **Superseded** — A newer skill covers the same domain with better content and triggers
- **Domain moved** — The topic no longer belongs in its current domain (e.g., a trading risk pattern that evolved into a general coding pattern)

**Sunset timeline:**
- **Day 0:** Mark deprecated, publish migration guide
- **Day +30:** Stop indexing as auto-loadable, keep manual access via `/skill`
- **Day +90:** Archive to `.archive/`, remove from skills-index.json active list
- **Day +365:** Purge archived copy (or keep indefinitely if requested)

---

### BAD vs GOOD Examples Across Lifecycle Stages

#### Versioning — BAD vs GOOD

```python
# ❌ BAD: Bumping version without classifying the change type
version = "1.2.3"
new_version = version + ".1"  # Random string concatenation, no semantics

# ✅ GOOD: Using the classification function with explicit rationale
old_ver = "1.2.3"
bump_type, new_ver = classify_version_bump(old_ver, "minor")
assert new_ver == "1.3.0", f"Expected 1.3.0, got {new_ver}"
# Rationale: Added a new ATR-based pattern — additive, non-breaking → MINOR
```

#### Deprecation — BAD vs GOOD

```markdown
<!-- ❌ BAD: No banner, no migration path, just delete the file -->
rm skills/agent/old-skill/SKILL.md

<!-- ✅ GOOD: Mark deprecated with banner and migration guide -->
# Old Skill Name
<!-- ⚠️ DEPRECATED: Functionality merged into skill-engineering -->
<!-- Replaced by: `skill-engineering` -->
<!-- Deprecated: 2026-05-19 -->
```

#### Cross-Reference Integrity — BAD vs GOOD

```yaml
# ❌ BAD: Related-skills references a directory that does not exist
related-skills: skill-engineering, phantom-nonexistent-skill, coding-code-review

# ✅ GOOD: All referenced skills exist and reciprocate
related-skills: skill-engineering, skill-router-system, skill-audit
```

---

## Constraints

### MUST DO
- Classify every version bump as MAJOR, MINOR, or PATCH before editing frontmatter — never guess
- Write a migration guide whenever deprecating a skill whose triggers overlap with other active skills
- Run backward compatibility checks against the full skills/ tree before publishing any MAJOR change
- Update `skills-index.json` and regenerate README.md after every version change
- Maintain the archive for at least 90 days after sunset date to allow dependent tools to adjust

### MUST NOT DO
- Delete a deprecated skill without first archiving it — users may still load it manually via `/skill <name>`
- Change trigger terms without running the backward compatibility checker first
- Bump only the PATCH version when removing workflow steps or patterns (that is at minimum a MINOR change)
- Leave orphaned entries in other skills' `related-skills` fields after retirement
- Use semantic versioning for the skill directory name — only bump it inside frontmatter

---

## Output Template

When applying this skill to manage a skill's lifecycle, produce:

1. **Version Classification Report** — Old version, change type (MAJOR/MINOR/PATCH), new version, and rationale referencing specific sections changed
2. **Backward Compatibility Results** — List of dependent skills checked, any trigger overlap issues found, and recommended actions
3. **Migration Guide** (if deprecating) — File path to the generated guide, affected skills list, timeline summary
4. **Cross-Reference Summary** — How many skills reference this one, which ones need updating, confirmation that all `related-skills` paths resolve
5. **Archive Manifest** (if retiring) — Source path, archive destination, sunset date, replacement skill name

---

## Related Skills

| Skill | Purpose |
|-------|---------|
| `skill-engineering` | Creating new skills from scratch — use before managing a new skill's lifecycle |
| `skill-router-system` | Understanding how the router index works — necessary context for deprecation and retirement steps |
| `skill-audit` | Assessing whether a skill has earned its place before deciding to deprecate or retire it |

## Live References

> Authoritative documentation links for this domain. The model follows markdown links at load time to resolve external references and inline content.

- [Semantic Versioning 2.0.0](https://semver.org/) — The semver specification for managing skill version numbers, deprecation signals, and compatibility
- [API Deprecation Best Practices (Microsoft)](https://learn.microsoft.com/en-us/azure/api-management/api-management-versioning) — Microsoft's guidance on API lifecycle management applicable to skill retirement workflows
- [Backward Compatibility Guidelines (Google)](https://cloud.google.com/apis/design/versioning) — Google Cloud's standards for maintaining backward compatibility during service evolution
- [Software Retirement and Migration Patterns (OWASP)](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/01-Information_Gathering/) — OWASP guidance on secure decommissioning of software components
- [Change Management Frameworks (ITIL 4)](https://www.axelos.com/certifications/itil-certifications/itil-4-foundation) — ITIL 4 standards for managing service lifecycle transitions including deprecation and retirement

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…