--- name: Plugin Manifest Sync description: Reconcile plugin.yaml with Betty Framework registries --- # docs.sync.plugin_manifest ## Overview **docs.sync.plugin_manifest** is a validation and reconciliation tool that compares `plugin.yaml` against Betty Framework's registry files to ensure consistency and completeness. It identifies missing commands, orphaned entries, metadata mismatches, and suggests corrections. ## Purpose Ensures synchronization between: - **Skill Registry** (`registry/skills.json`) – Active skills with entrypoints - **Command Registry** (`registry/commands.json`) – Slash commands - **Plugin Configuration** (`plugin.yaml`) – Claude Code plugin manifest This skill helps maintain plugin.yaml accuracy by detecting: - Active skills missing from plugin.yaml - Orphaned commands in plugin.yaml not found in registries - Metadata inconsistencies (permissions, runtime, handlers) - Missing metadata that should be added ## What It Does 1. **Loads Registries**: Reads `skills.json` and `commands.json` 2. **Loads Plugin**: Reads current `plugin.yaml` 3. **Builds Indexes**: Creates lookup tables for both registries and plugin 4. **Compares Entries**: Identifies missing, orphaned, and mismatched commands 5. **Analyzes Metadata**: Checks permissions, runtime, handlers, descriptions 6. **Generates Preview**: Creates `plugin.preview.yaml` with suggested updates 7. **Creates Report**: Outputs `plugin_manifest_diff.md` with detailed analysis 8. **Provides Summary**: Displays key findings and recommendations ## Usage ### Basic Usage ```bash python skills/docs.sync.plugin_manifest/plugin_manifest_sync.py ``` No arguments required - reads from standard locations. ### Via Betty CLI ```bash /docs/sync/plugin-manifest ``` ### Expected File Structure ``` betty/ ├── registry/ │ ├── skills.json # Source of truth for skills │ └── commands.json # Source of truth for commands ├── plugin.yaml # Current plugin manifest ├── plugin.preview.yaml # Generated preview (output) └── plugin_manifest_diff.md # Generated report (output) ``` ## Behavior ### 1. Registry Loading Reads and parses: - `registry/skills.json` – All registered skills - `registry/commands.json` – All registered commands Only processes entries with `status: active`. ### 2. Plugin Loading Reads and parses: - `plugin.yaml` – Current plugin configuration Extracts all command definitions. ### 3. Index Building **Registry Index**: Maps command names to their registry sources ```python { "skill/define": { "type": "skill", "source": "skill.define", "skill": {...}, "entrypoint": {...} }, "api/validate": { "type": "skill", "source": "api.validate", "skill": {...}, "entrypoint": {...} } } ``` **Plugin Index**: Maps command names to plugin entries ```python { "skill/define": { "name": "skill/define", "handler": {...}, "permissions": [...] } } ``` ### 4. Comparison Analysis Performs four types of checks: #### Missing Commands Commands in registry but not in plugin.yaml: ``` - skill/create (active in registry, missing from plugin) - api/validate (active in registry, missing from plugin) ``` #### Orphaned Commands Commands in plugin.yaml but not in registry: ``` - old/deprecated (in plugin but not registered) - test/removed (in plugin but removed from registry) ``` #### Metadata Mismatches Commands present in both but with different metadata: **Runtime Mismatch**: ``` - skill/define: - Registry: python - Plugin: node ``` **Permission Mismatch**: ``` - api/validate: - Missing: filesystem:read - Extra: network:write ``` **Handler Mismatch**: ``` - skill/create: - Registry: skills/skill.create/skill_create.py - Plugin: skills/skill.create/old_handler.py ``` **Description Mismatch**: ``` - agent/run: - Registry: "Execute a Betty agent..." - Plugin: "Run agent" ``` #### Missing Metadata Suggestions Identifies registry entries missing recommended metadata: ``` - hook/define: Consider adding permissions metadata - test/skill: Consider adding description ``` ### 5. Preview Generation Creates `plugin.preview.yaml` by: - Taking all active commands from registries - Converting to plugin.yaml format - Including all metadata from registries - Adding generation timestamp - Preserving existing plugin metadata (author, license, etc.) ### 6. Report Generation Creates `plugin_manifest_diff.md` with: - Executive summary - Lists of missing commands - Lists of orphaned commands - Detailed metadata issues - Metadata suggestions ## Outputs ### Success Response ```json { "ok": true, "status": "success", "preview_path": "/home/user/betty/plugin.preview.yaml", "report_path": "/home/user/betty/plugin_manifest_diff.md", "reconciliation": { "missing_commands": [...], "orphaned_commands": [...], "metadata_issues": [...], "metadata_suggestions": [...], "total_registry_commands": 19, "total_plugin_commands": 18 } } ``` ### Console Output ``` ============================================================ PLUGIN MANIFEST RECONCILIATION COMPLETE ============================================================ 📊 Summary: - Commands in registry: 19 - Commands in plugin.yaml: 18 - Missing from plugin.yaml: 2 - Orphaned in plugin.yaml: 1 - Metadata issues: 3 - Metadata suggestions: 2 📄 Output files: - Preview: /home/user/betty/plugin.preview.yaml - Diff report: /home/user/betty/plugin_manifest_diff.md ⚠️ 2 command(s) missing from plugin.yaml: - registry/query (registry.query) - hook/simulate (hook.simulate) ⚠️ 1 orphaned command(s) in plugin.yaml: - old/deprecated ✅ Review plugin_manifest_diff.md for full details ============================================================ ``` ### Failure Response ```json { "ok": false, "status": "failed", "error": "Failed to parse JSON from registry/skills.json" } ``` ## Generated Files ### plugin.preview.yaml Updated plugin manifest with all active registry commands: ```yaml # Betty Framework - Claude Code Plugin (Preview) # Generated by docs.sync.plugin_manifest skill # Review changes before applying to plugin.yaml name: betty-framework version: 1.0.0 description: Betty Framework - Structured AI-assisted engineering author: name: RiskExec email: platform@riskexec.com url: https://github.com/epieczko/betty license: MIT metadata: generated_at: "2025-10-23T20:00:00.000000+00:00" generated_by: docs.sync.plugin_manifest skill command_count: 19 commands: - name: skill/define description: Validate a Claude Code skill manifest handler: runtime: python script: skills/skill.define/skill_define.py parameters: - name: manifest_path type: string required: true description: Path to skill.yaml file permissions: - filesystem:read - filesystem:write # ... more commands ... ``` ### plugin_manifest_diff.md Detailed reconciliation report: ```markdown # Plugin Manifest Reconciliation Report Generated: 2025-10-23T20:00:00.000000+00:00 ## Summary - Total commands in registry: 19 - Total commands in plugin.yaml: 18 - Missing from plugin.yaml: 2 - Orphaned in plugin.yaml: 1 - Metadata issues: 3 - Metadata suggestions: 2 ## Missing Commands (in registry but not in plugin.yaml) - **registry/query** (skill: registry.query) - **hook/simulate** (skill: hook.simulate) ## Orphaned Commands (in plugin.yaml but not in registry) - **old/deprecated** ## Metadata Issues - **skill/create**: Permissions Mismatch - Missing: process:execute - Extra: network:http - **api/validate**: Handler Mismatch - Registry: `skills/api.validate/api_validate.py` - Plugin: `skills/api.validate/validator.py` - **agent/run**: Runtime Mismatch - Registry: `python` - Plugin: `node` ## Metadata Suggestions - **hook/define** (permissions): Consider adding permissions metadata - **test/skill** (description): Consider adding description ``` ## Examples ### Example 1: Routine Sync Check **Scenario**: Regular validation after making registry changes ```bash # Make some registry updates /skill/define skills/new.skill/skill.yaml # Check for discrepancies /docs/sync/plugin-manifest # Review the report cat plugin_manifest_diff.md # If changes look good, apply them cp plugin.preview.yaml plugin.yaml ``` **Output**: ``` ============================================================ PLUGIN MANIFEST RECONCILIATION COMPLETE ============================================================ 📊 Summary: - Commands in registry: 20 - Commands in plugin.yaml: 19 - Missing from plugin.yaml: 1 - Orphaned in plugin.yaml: 0 - Metadata issues: 0 - Metadata suggestions: 0 ⚠️ 1 command(s) missing from plugin.yaml: - new/skill (new.skill) ✅ Review plugin_manifest_diff.md for full details ``` ### Example 2: Detecting Orphaned Commands **Scenario**: A skill was removed from registry but command remains in plugin.yaml ```bash # Remove skill from registry rm -rf skills/deprecated.skill/ # Run reconciliation /docs/sync/plugin-manifest # Check report cat plugin_manifest_diff.md ``` **Output**: ``` ============================================================ PLUGIN MANIFEST RECONCILIATION COMPLETE ============================================================ 📊 Summary: - Commands in registry: 18 - Commands in plugin.yaml: 19 - Missing from plugin.yaml: 0 - Orphaned in plugin.yaml: 1 - Metadata issues: 0 - Metadata suggestions: 0 ⚠️ 1 orphaned command(s) in plugin.yaml: - deprecated/skill ✅ Review plugin_manifest_diff.md for full details ``` ### Example 3: Finding Metadata Mismatches **Scenario**: Registry was updated but plugin.yaml wasn't synced ```bash # Update skill permissions in registry /skill/define skills/api.validate/skill.yaml # Check for differences /docs/sync/plugin-manifest # Review specific mismatches grep -A 5 "Metadata Issues" plugin_manifest_diff.md ``` **Report Output**: ```markdown ## Metadata Issues - **api/validate**: Permissions Mismatch - Missing: network:http - Extra: filesystem:write ``` ### Example 4: Pre-Commit Validation **Scenario**: Validate plugin.yaml before committing changes ```bash # Before committing /docs/sync/plugin-manifest # If discrepancies found, fix them if [ $? -eq 0 ]; then # Review and apply changes diff plugin.yaml plugin.preview.yaml cp plugin.preview.yaml plugin.yaml fi # Commit changes git add plugin.yaml git commit -m "Sync plugin.yaml with registries" ``` ### Example 5: CI/CD Integration **Scenario**: Automated validation in CI pipeline ```yaml # .github/workflows/validate-plugin.yml name: Validate Plugin Manifest on: [push, pull_request] jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Reconcile Plugin Manifest run: | python skills/docs.sync.plugin_manifest/plugin_manifest_sync.py # Check if there are discrepancies if grep -q "Missing from plugin.yaml: [1-9]" plugin_manifest_diff.md; then echo "❌ Plugin manifest has missing commands" cat plugin_manifest_diff.md exit 1 fi if grep -q "Orphaned in plugin.yaml: [1-9]" plugin_manifest_diff.md; then echo "❌ Plugin manifest has orphaned commands" cat plugin_manifest_diff.md exit 1 fi echo "✅ Plugin manifest is in sync" ``` ## Integration ### With plugin.sync Use reconciliation to verify before syncing: ```bash # Check current state /docs/sync/plugin-manifest # Review differences cat plugin_manifest_diff.md # If satisfied, run full sync /plugin/sync ``` ### With skill.define Validate after defining skills: ```bash # Define new skill /skill/define skills/my.skill/skill.yaml # Check plugin consistency /docs/sync/plugin-manifest # Apply changes if needed cp plugin.preview.yaml plugin.yaml ``` ### With Hooks Auto-check on registry changes: ```yaml # .claude/hooks.yaml - event: on_file_save pattern: "registry/*.json" command: python skills/docs.sync.plugin_manifest/plugin_manifest_sync.py blocking: false description: Check plugin manifest sync when registries change ``` ### With Workflows Include in skill lifecycle workflow: ```yaml # workflows/update_plugin.yaml steps: - skill: skill.define args: ["skills/new.skill/skill.yaml"] - skill: docs.sync.plugin_manifest args: [] - skill: plugin.sync args: [] ``` ## What Gets Reported ### ✅ Detected Issues - Active skills missing from plugin.yaml - Orphaned commands in plugin.yaml - Runtime mismatches (python vs node) - Permission mismatches (missing or extra) - Handler path mismatches - Description mismatches - Missing metadata (permissions, descriptions) ### ❌ Not Detected - Draft/inactive skills (intentionally excluded) - Malformed YAML syntax (causes failure) - Handler file existence (use plugin.sync for that) - Parameter schema validation ## Common Use Cases | Use Case | When to Use | |----------|-------------| | **Pre-commit check** | Before committing plugin.yaml changes | | **Post-registry update** | After adding/updating skills in registry | | **CI/CD validation** | Automated pipeline checks | | **Manual audit** | Periodic manual review of plugin state | | **Debugging** | When commands aren't appearing as expected | | **Migration** | After major registry restructuring | ## Common Errors | Error | Cause | Solution | |-------|-------|----------| | "Failed to parse JSON" | Invalid JSON in registry | Fix JSON syntax in registry files | | "Failed to parse YAML" | Invalid YAML in plugin.yaml | Fix YAML syntax in plugin.yaml | | "Registry file not found" | Missing registry files | Ensure registries exist in registry/ | | "Permission denied" | Cannot write output files | Check write permissions on directory | | All commands missing | Empty or invalid registries | Verify registry files are populated | ## Files Read - `registry/skills.json` – Skill registry (source of truth) - `registry/commands.json` – Command registry (source of truth) - `plugin.yaml` – Current plugin manifest (for comparison) ## Files Generated - `plugin.preview.yaml` – Updated plugin manifest preview - `plugin_manifest_diff.md` – Detailed reconciliation report ## Exit Codes - **0**: Success (reconciliation completed successfully) - **1**: Failure (error during reconciliation) Note: Discrepancies found are reported but don't cause failure (exit 0). Only parsing errors or system failures cause exit 1. ## Logging Logs reconciliation progress: ``` INFO: Starting plugin manifest reconciliation... INFO: Loading registry files... INFO: Loading plugin.yaml... INFO: Building registry index... INFO: Building plugin index... INFO: Comparing registries with plugin.yaml... INFO: Reconciling registries with plugin.yaml... INFO: Generating updated plugin.yaml... INFO: ✅ Written file to /home/user/betty/plugin.preview.yaml INFO: Generating diff report... INFO: ✅ Written diff report to /home/user/betty/plugin_manifest_diff.md ``` ## Best Practices 1. **Run Before Committing**: Always check sync status before committing plugin.yaml 2. **Review Diff Report**: Read the full report to understand all changes 3. **Validate Preview**: Review plugin.preview.yaml before applying 4. **Include in CI**: Add validation to your CI/CD pipeline 5. **Regular Audits**: Run periodic checks even without changes 6. **Address Orphans**: Remove orphaned commands promptly 7. **Fix Mismatches**: Resolve metadata mismatches to maintain consistency 8. **Keep Registries Clean**: Mark inactive skills as draft instead of deleting ## Workflow Integration ### Recommended Workflow ```bash # 1. Define or update skills /skill/define skills/my.skill/skill.yaml # 2. Check for discrepancies /docs/sync/plugin-manifest # 3. Review the report cat plugin_manifest_diff.md # 4. Review the preview diff plugin.yaml plugin.preview.yaml # 5. Apply changes if satisfied cp plugin.preview.yaml plugin.yaml # 6. Commit changes git add plugin.yaml registry/ git commit -m "Update plugin manifest" ``` ### Alternative: Auto-Sync Workflow ```bash # 1. Define or update skills /skill/define skills/my.skill/skill.yaml # 2. Run full sync (overwrites plugin.yaml) /plugin/sync # 3. Validate the result /docs/sync/plugin-manifest # 4. If clean, commit git add plugin.yaml registry/ git commit -m "Update plugin manifest" ``` ## Troubleshooting ### Plugin.yaml Shows as Out of Sync **Problem**: Reconciliation reports missing or orphaned commands **Solutions**: 1. Run `/plugin/sync` to regenerate plugin.yaml from registries 2. Review and apply `plugin.preview.yaml` manually 3. Check if skills are marked as `active` in registry 4. Verify skills have `entrypoints` defined ### Metadata Mismatches Reported **Problem**: Registry and plugin have different permissions/runtime/handlers **Solutions**: 1. Update skill.yaml with correct metadata 2. Run `/skill/define` to register changes 3. Run `/docs/sync/plugin-manifest` to verify 4. Apply plugin.preview.yaml or run `/plugin/sync` ### Orphaned Commands Found **Problem**: Commands in plugin.yaml not found in registry **Solutions**: 1. Check if skill was removed from registry 2. Verify skill status is `active` in registry 3. Re-register the skill if it should exist 4. Remove from plugin.yaml if intentionally deprecated ### Preview File Not Generated **Problem**: plugin.preview.yaml missing after running skill **Solutions**: 1. Check write permissions on betty/ directory 2. Verify registries are readable 3. Check logs for errors 4. Ensure plugin.yaml exists and is valid ## Architecture ### Skill Category **Documentation & Infrastructure** – Maintains consistency between registry and plugin configuration layers. ### Design Principles - **Non-Destructive**: Never modifies plugin.yaml directly - **Comprehensive**: Reports all types of discrepancies - **Actionable**: Provides preview file ready to apply - **Transparent**: Detailed report explains all findings - **Idempotent**: Can be run multiple times safely ## See Also - **plugin.sync** – Generate plugin.yaml from registries ([SKILL.md](../plugin.sync/SKILL.md)) - **skill.define** – Validate and register skills ([SKILL.md](../skill.define/SKILL.md)) - **registry.update** – Update skill registry ([SKILL.md](../registry.update/SKILL.md)) - **Betty Architecture** – Framework overview ([betty-architecture.md](../../docs/betty-architecture.md)) ## Dependencies - **plugin.sync**: Plugin generation infrastructure - **registry.update**: Registry management - **betty.config**: Configuration constants and paths - **betty.logging_utils**: Logging infrastructure ## Status **Active** – Production-ready documentation and validation skill ## Version History - **0.1.0** (Oct 2025) – Initial implementation with full reconciliation, preview generation, and diff reporting