Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 18:26:08 +08:00
commit 8f22ddf339
295 changed files with 59710 additions and 0 deletions

View File

@@ -0,0 +1,732 @@
---
name: Plugin Build
description: Bundle plugin directory into a deployable Claude Code plugin package
---
# plugin.build
## Overview
**plugin.build** is the packaging tool that bundles your Betty Framework plugin into a distributable archive ready for deployment to Claude Code. It validates all entrypoints, gathers necessary files, and creates versioned packages with checksums.
## Purpose
Automates the creation of deployable plugin packages by:
- **Validating** all declared entrypoints and handler files
- **Gathering** all necessary plugin files (skills, utilities, registries)
- **Packaging** into `.tar.gz` or `.zip` archives
- **Generating** checksums for package verification
- **Reporting** validation results and build metrics
This eliminates manual packaging errors and ensures consistent, reproducible plugin distributions.
## What It Does
1. **Loads plugin.yaml**: Reads the plugin configuration
2. **Validates Entrypoints**: Checks that all command handlers exist on disk
3. **Gathers Files**: Collects skills, utilities, registries, and documentation
4. **Creates Package**: Bundles everything into a versioned archive
5. **Calculates Checksums**: Generates MD5 and SHA256 hashes
6. **Generates Manifest**: Creates manifest.json with entrypoint summary and checksums
7. **Creates Preview**: Generates plugin.preview.yaml for review before deployment
8. **Generates Report**: Outputs detailed build metrics as JSON
9. **Reports Issues**: Identifies missing files or validation errors
## Usage
### Basic Usage
```bash
python skills/plugin.build/plugin_build.py
```
Builds with defaults:
- Plugin: `./plugin.yaml`
- Format: `tar.gz`
- Output: `./dist/`
### Via Betty CLI
```bash
/plugin/build
```
### Custom Plugin Path
```bash
python skills/plugin.build/plugin_build.py /path/to/plugin.yaml
```
### Specify Output Format
```bash
python skills/plugin.build/plugin_build.py --format=zip
```
```bash
python skills/plugin.build/plugin_build.py --format=tar.gz
```
### Custom Output Directory
```bash
python skills/plugin.build/plugin_build.py --output-dir=/tmp/packages
```
### Full Options
```bash
python skills/plugin.build/plugin_build.py \
/custom/path/plugin.yaml \
--format=zip \
--output-dir=/var/packages
```
## Command-Line Arguments
| Argument | Type | Default | Description |
|----------|------|---------|-------------|
| `plugin_path` | Positional | `./plugin.yaml` | Path to plugin.yaml file |
| `--format` | Option | `tar.gz` | Package format (tar.gz or zip) |
| `--output-dir` | Option | `./dist` | Output directory for packages |
## Output Files
### Package Archive
**Naming convention**: `{plugin-name}-{version}.{format}`
Examples:
- `betty-framework-1.0.0.tar.gz`
- `betty-framework-1.0.0.zip`
**Location**: `{output-dir}/{package-name}.{format}`
### Manifest File
**Naming convention**: `manifest.json`
**Location**: `{output-dir}/manifest.json`
Contains plugin metadata, entrypoint summary, and package checksums. This is the primary file for plugin distribution and installation.
### Plugin Preview
**Naming convention**: `plugin.preview.yaml`
**Location**: `{output-dir}/plugin.preview.yaml`
Contains the current plugin configuration for review before deployment. Useful for comparing changes or validating the plugin structure.
### Build Report
**Naming convention**: `{plugin-name}-{version}-build-report.json`
Example:
- `betty-framework-1.0.0-build-report.json`
**Location**: `{output-dir}/{package-name}-build-report.json`
## Package Structure
The generated archive contains:
```
betty-framework-1.0.0/
├── plugin.yaml # Plugin manifest
├── requirements.txt # Python dependencies
├── README.md # Documentation (if exists)
├── LICENSE # License file (if exists)
├── CHANGELOG.md # Change log (if exists)
├── betty/ # Core utility package
│ ├── __init__.py
│ ├── config.py
│ ├── validation.py
│ ├── logging_utils.py
│ ├── file_utils.py
│ └── errors.py
├── registry/ # Registry files
│ ├── skills.json
│ ├── commands.json
│ ├── hooks.json
│ └── agents.json
└── skills/ # All active skills
├── api.define/
│ ├── skill.yaml
│ ├── SKILL.md
│ └── api_define.py
├── api.validate/
│ ├── skill.yaml
│ ├── SKILL.md
│ └── api_validate.py
└── ... (all other skills)
```
## Manifest Schema
The `manifest.json` file is the primary metadata file for plugin distribution:
```json
{
"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": {
"homepage": "https://github.com/epieczko/betty",
"repository": "https://github.com/epieczko/betty",
"documentation": "https://github.com/epieczko/betty/tree/main/docs",
"tags": ["framework", "api-development", "workflow"],
"generated_at": "2025-10-23T12:34:56.789012+00:00"
},
"requirements": {
"python": ">=3.11",
"packages": ["pyyaml"]
},
"permissions": ["filesystem:read", "filesystem:write", "process:execute"],
"package": {
"filename": "betty-framework-1.0.0.tar.gz",
"size_bytes": 245760,
"checksums": {
"md5": "a1b2c3d4e5f6...",
"sha256": "1234567890abcdef..."
}
},
"entrypoints": [
{
"command": "skill/define",
"handler": "skills/skill.define/skill_define.py",
"runtime": "python"
}
],
"commands_count": 18,
"agents": [
{
"name": "api.designer",
"description": "Design APIs with iterative refinement"
}
]
}
```
## Build Report Schema
```json
{
"build_timestamp": "2025-10-23T12:34:56.789012+00:00",
"plugin": {
"name": "betty-framework",
"version": "1.0.0",
"description": "Betty Framework - Structured AI-assisted engineering"
},
"validation": {
"total_commands": 18,
"valid_entrypoints": 18,
"missing_files": [],
"has_errors": false
},
"package": {
"path": "/home/user/betty/dist/betty-framework-1.0.0.tar.gz",
"size_bytes": 245760,
"size_human": "240.00 KB",
"files_count": 127,
"format": "tar.gz",
"checksums": {
"md5": "a1b2c3d4e5f6...",
"sha256": "1234567890abcdef..."
}
},
"entrypoints": [
{
"command": "skill/define",
"handler": "skills/skill.define/skill_define.py",
"runtime": "python",
"path": "/home/user/betty/skills/skill.define/skill_define.py"
}
]
}
```
## Outputs
### Success Response
```json
{
"ok": true,
"status": "success",
"package_path": "/home/user/betty/dist/betty-framework-1.0.0.tar.gz",
"report_path": "/home/user/betty/dist/betty-framework-1.0.0-build-report.json",
"build_report": { ... }
}
```
### Success with Warnings
```json
{
"ok": false,
"status": "success_with_warnings",
"package_path": "/home/user/betty/dist/betty-framework-1.0.0.tar.gz",
"report_path": "/home/user/betty/dist/betty-framework-1.0.0-build-report.json",
"build_report": {
"validation": {
"missing_files": [
"Command 'api.broken': handler not found at skills/api.broken/api_broken.py"
],
"has_errors": true
}
}
}
```
### Failure Response
```json
{
"ok": false,
"status": "failed",
"error": "plugin.yaml not found: /home/user/betty/plugin.yaml"
}
```
## Behavior
### 1. Plugin Loading
Reads and parses `plugin.yaml`:
- Validates YAML syntax
- Extracts plugin name, version, description
- Identifies all command entrypoints
### 2. Entrypoint Validation
For each command in `plugin.yaml`:
- Extracts handler script path
- Checks file existence on disk
- Reports valid and missing handlers
- Logs validation results
**Valid entrypoint**:
```yaml
- name: skill/validate
handler:
runtime: python
script: skills/skill.define/skill_define.py
```
**Missing handler** (reports warning):
```yaml
- name: broken/command
handler:
runtime: python
script: skills/broken/missing.py # File doesn't exist
```
### 3. File Gathering
Automatically includes:
**Always included**:
- `plugin.yaml` Plugin manifest
- `skills/*/` All skill directories referenced in commands
- `betty/` Core utility package
- `registry/*.json` All registry files
**Conditionally included** (if exist):
- `requirements.txt` Python dependencies
- `README.md` Plugin documentation
- `LICENSE` License file
- `CHANGELOG.md` Version history
**Excluded**:
- `__pycache__/` directories
- `.pyc` compiled Python files
- Hidden files (starting with `.`)
- Build artifacts and temporary files
### 4. Package Creation
**tar.gz format**:
- GZIP compression
- Preserves file permissions
- Cross-platform compatible
- Standard for Python packages
**zip format**:
- ZIP compression
- Wide compatibility
- Good for Windows environments
- Easy to extract without CLI tools
### 5. Checksum Generation
Calculates two checksums:
**MD5**: Fast, widely supported
```
a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
```
**SHA256**: Cryptographically secure
```
1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef
```
Use checksums to verify package integrity after download or transfer.
## Examples
### Example 1: Standard Build
**Scenario**: Build Betty Framework plugin for distribution
```bash
# Ensure plugin.yaml is up to date
/plugin/sync
# Build the package
/plugin/build
```
**Output**:
```
INFO: 🏗️ Starting plugin build...
INFO: 📄 Plugin: /home/user/betty/plugin.yaml
INFO: 📦 Format: tar.gz
INFO: 📁 Output: /home/user/betty/dist
INFO: ✅ Loaded plugin.yaml from /home/user/betty/plugin.yaml
INFO: 📝 Validating 18 command entrypoints...
INFO: 📦 Gathering files from 16 skill directories...
INFO: 📦 Adding betty/ utility package...
INFO: 📦 Adding registry/ files...
INFO: 📦 Total files to package: 127
INFO: 🗜️ Creating tar.gz archive: /home/user/betty/dist/betty-framework-1.0.0.tar.gz
INFO: 🔐 Calculating checksums...
INFO: MD5: a1b2c3d4e5f6...
INFO: SHA256: 1234567890ab...
INFO: 📊 Build report: /home/user/betty/dist/betty-framework-1.0.0-build-report.json
INFO: 📋 Manifest: /home/user/betty/dist/manifest.json
INFO: 📋 Preview file created: /home/user/betty/dist/plugin.preview.yaml
INFO:
============================================================
INFO: 🎉 BUILD COMPLETE
============================================================
INFO: 📦 Package: /home/user/betty/dist/betty-framework-1.0.0.tar.gz
INFO: 📊 Report: /home/user/betty/dist/betty-framework-1.0.0-build-report.json
INFO: 📋 Manifest: /home/user/betty/dist/manifest.json
INFO: 👁️ Preview: /home/user/betty/dist/plugin.preview.yaml
INFO: ✅ Commands: 18/18
INFO: 📏 Size: 240.00 KB
INFO: 📝 Files: 127
============================================================
```
### Example 2: Build as ZIP
**Scenario**: Create Windows-friendly package
```bash
python skills/plugin.build/plugin_build.py --format=zip
```
**Result**: `dist/betty-framework-1.0.0.zip`
### Example 3: Build with Custom Output
**Scenario**: Build to specific release directory
```bash
python skills/plugin.build/plugin_build.py \
--format=tar.gz \
--output-dir=releases/v1.0.0
```
**Result**:
- `releases/v1.0.0/betty-framework-1.0.0.tar.gz`
- `releases/v1.0.0/betty-framework-1.0.0-build-report.json`
### Example 4: Detecting Missing Handlers
**Scenario**: Some handlers are missing
```bash
# Remove a handler file
rm skills/api.validate/api_validate.py
# Try to build
/plugin/build
```
**Output**:
```
INFO: 📝 Validating 18 command entrypoints...
WARNING: ❌ skill/api/validate: skills/api.validate/api_validate.py (not found)
INFO: ⚠️ Found 1 missing files:
INFO: - Command 'skill/api/validate': handler not found at skills/api.validate/api_validate.py
INFO: 📦 Gathering files from 15 skill directories...
...
INFO: ============================================================
INFO: 🎉 BUILD COMPLETE
INFO: ============================================================
INFO: ✅ Commands: 17/18
INFO: ⚠️ Warnings: 1
```
**Exit code**: 1 (failure due to validation errors)
### Example 5: Build Workflow
**Scenario**: Complete release workflow
```bash
# 1. Update registries
/registry/update
# 2. Sync plugin.yaml
/plugin/sync
# 3. Build package
/plugin/build
# 4. Verify package
tar -tzf dist/betty-framework-1.0.0.tar.gz | head -20
# 5. Check build report
cat dist/betty-framework-1.0.0-build-report.json | jq .
```
## Integration
### With plugin.sync
Always sync before building:
```bash
/plugin/sync && /plugin/build
```
### With Workflows
Include in release workflow:
```yaml
# workflows/plugin_release.yaml
name: plugin_release
version: 1.0.0
description: Release workflow for Betty Framework plugin
steps:
- skill: registry.update
description: Update all registries
- skill: plugin.sync
description: Generate plugin.yaml
- skill: plugin.build
args: ["--format=tar.gz"]
description: Build tar.gz package
- skill: plugin.build
args: ["--format=zip"]
description: Build zip package
```
### With CI/CD
Add to GitHub Actions:
```yaml
# .github/workflows/release.yml
- name: Build Plugin Package
run: |
python skills/plugin.sync/plugin_sync.py
python skills/plugin.build/plugin_build.py --format=tar.gz
python skills/plugin.build/plugin_build.py --format=zip
- name: Upload Packages
uses: actions/upload-artifact@v3
with:
name: plugin-packages
path: dist/betty-framework-*
```
## Validation Rules
### Entrypoint Validation
**Valid entrypoint**:
- Command name is defined
- Handler section exists
- Handler script path is specified
- Handler file exists on disk
- Runtime is specified
**Invalid entrypoint** (triggers warning):
- Missing handler script path
- Handler file doesn't exist
- Empty command name
### File Gathering Rules
**Skill directories included if**:
- Referenced in at least one command handler
- Contains valid handler file
**Files excluded**:
- Python cache files (`__pycache__`, `.pyc`)
- Hidden files (`.git`, `.env`, etc.)
- Build artifacts (`dist/`, `build/`)
- IDE files (`.vscode/`, `.idea/`)
## Common Errors
| Error | Cause | Solution |
|-------|-------|----------|
| "plugin.yaml not found" | Missing plugin.yaml | Run `/plugin/sync` first |
| "Invalid YAML" | Syntax error in plugin.yaml | Fix YAML syntax |
| "Unsupported output format" | Invalid --format value | Use `tar.gz` or `zip` |
| "Handler not found" | Missing handler file | Create handler or fix path |
| "Permission denied" | Cannot write to output dir | Check directory permissions |
## Files Read
- `plugin.yaml` Plugin manifest
- `skills/*/skill.yaml` Skill manifests (indirect via handlers)
- `skills/*/*.py` Handler scripts
- `betty/*.py` Utility modules
- `registry/*.json` Registry files
- `requirements.txt` Dependencies (if exists)
- `README.md`, `LICENSE`, `CHANGELOG.md` Documentation (if exist)
## Files Modified
- `{output-dir}/{plugin-name}-{version}.{format}` Created package archive
- `{output-dir}/{plugin-name}-{version}-build-report.json` Created build report
- `{output-dir}/manifest.json` Created plugin manifest with checksums and entrypoints
- `{output-dir}/plugin.preview.yaml` Created plugin preview for review
## Exit Codes
- **0**: Success (all handlers valid, package created)
- **1**: Failure (missing handlers or build error)
## Logging
Logs build progress with emojis for clarity:
```
INFO: 🏗️ Starting plugin build...
INFO: 📄 Plugin: /home/user/betty/plugin.yaml
INFO: ✅ Loaded plugin.yaml
INFO: 📝 Validating entrypoints...
INFO: 📦 Gathering files...
INFO: 🗜️ Creating tar.gz archive...
INFO: 🔐 Calculating checksums...
INFO: 📊 Build report written
INFO: 🎉 BUILD COMPLETE
```
## Best Practices
1. **Always Sync First**: Run `/plugin/sync` before `/plugin/build`
2. **Validate Before Building**: Ensure all skills are registered and active
3. **Check Build Reports**: Review validation warnings before distribution
4. **Verify Checksums**: Use checksums to verify package integrity
5. **Version Consistently**: Match plugin version with git tags
6. **Test Extraction**: Verify packages extract correctly
7. **Document Changes**: Keep CHANGELOG.md updated
## Troubleshooting
### Missing Files in Package
**Problem**: Expected files not in archive
**Solutions**:
- Ensure files exist in source directory
- Check that skills are referenced in commands
- Verify files aren't excluded (e.g., `.pyc`, `__pycache__`)
- Check file permissions
### Handler Validation Failures
**Problem**: Handlers marked as missing but files exist
**Solutions**:
- Verify exact path in plugin.yaml matches file location
- Check case sensitivity in file paths
- Ensure handler files have correct names
- Run `/plugin/sync` to update paths
### Package Size Too Large
**Problem**: Archive file is very large
**Solutions**:
- Remove unused skills from plugin.yaml
- Check for accidentally included large files
- Review skill directories for unnecessary data
- Consider splitting into multiple plugins
### Build Fails with Permission Error
**Problem**: Cannot write to output directory
**Solutions**:
- Create output directory with proper permissions
- Check disk space availability
- Verify write access to output directory
- Try different output directory with `--output-dir`
## Architecture
### Skill Category
**Infrastructure** Plugin.build is part of the distribution layer, preparing plugins for deployment.
### Design Principles
- **Validation First**: Check all handlers before packaging
- **Complete Packages**: Include all necessary dependencies
- **Reproducible**: Same source creates identical packages
- **Verifiable**: Checksums ensure package integrity
- **Transparent**: Detailed reporting of included files
- **Flexible**: Support multiple archive formats
### Package Philosophy
The package includes everything needed to run the plugin:
- **Skills**: All command handlers and manifests
- **Utilities**: Core betty package for shared functionality
- **Registries**: Skill, command, and hook definitions
- **Dependencies**: Python requirements
- **Documentation**: README, LICENSE, CHANGELOG
This creates a self-contained, portable plugin distribution.
## See Also
- **plugin.sync** Generate plugin.yaml ([SKILL.md](../plugin.sync/SKILL.md))
- **skill.define** Validate and register skills ([SKILL.md](../skill.define/SKILL.md))
- **registry.update** Update registries ([SKILL.md](../registry.update/SKILL.md))
- **Betty Distribution** Plugin marketplace guide ([docs/distribution.md](../../docs/distribution.md))
## Dependencies
- **plugin.sync**: Generate plugin.yaml before building
- **betty.config**: Configuration constants and paths
- **betty.logging_utils**: Logging infrastructure
## Status
**Active** Production-ready infrastructure skill
## Version History
- **0.1.0** (Oct 2025) Initial implementation with tar.gz/zip support, validation, and checksums