# OCLAWMA Skill Packaging Format

This document defines the standard for creating pip-installable skills for OCLAWMA.

## Overview

OCLAWMA skills can be distributed as Python packages via PyPI. This allows:
- Easy installation: `pip install oclawma-skill-docker`
- Version management through standard Python tooling
- Automatic discovery via Python entry points
- Dependency management via `requirements`

## Package Naming Convention

All pip-installable OCLAWMA skills **MUST** use the naming convention:

```
oclawma-skill-{name}
```

Examples:
- `oclawma-skill-docker` - Docker container management
- `oclawma-skill-git` - Git repository operations
- `oclawma-skill-kubernetes` - Kubernetes cluster management
- `oclawma-skill-aws` - AWS cloud operations

The internal skill `name` (used in code) should match the `{name}` portion of the package name.

## Package Structure

```
oclawma-skill-example/
├── pyproject.toml          # Package configuration
├── README.md               # General documentation
├── SKILL.md                # **REQUIRED** - Skill specification
├── src/
│   └── oclawma_skill_example/
│       ├── __init__.py     # Package init with entry point
│       └── skill.py        # Skill implementation
└── tests/
    └── test_skill.py
```

## Entry Points

Skills register themselves using Python entry points in `pyproject.toml`:

```toml
[project.entry-points."oclawma.skills"]
example = "oclawma_skill_example:SkillClass"
```

The entry point format is:
- **Key**: The skill name (without `oclawma-skill-` prefix)
- **Value**: The Python path to the skill class (e.g., `module.path:ClassName`)

### Multiple Skills per Package

A single package can provide multiple skills:

```toml
[project.entry-points."oclawma.skills"]
docker = "oclawma_skill_containers.docker:DockerSkill"
kubernetes = "oclawma_skill_containers.k8s:KubernetesSkill"
podman = "oclawma_skill_containers.podman:PodmanSkill"
```

## SKILL.md Format

Every pip-installable skill **MUST** include a `SKILL.md` file at the package root:

```markdown
# Skill: {name}

## Metadata

| Field | Value |
|-------|-------|
| **Name** | `{name}` |
| **Version** | `{version}` |
| **Package** | `oclawma-skill-{name}` |
| **Category** | `{category}` |
| **Author** | `{author}` |
| **License** | `{license}` |
| **Python** | `>={python_version}` |

## Description

{description}

## Installation

```bash
pip install oclawma-skill-{name}
```

## Configuration

{configuration_instructions}

## Tools

### `{tool_name}`

{tool_description}

**Parameters:**

| Name | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `{param}` | `{type}` | {yes/no} | `{default}` | {description} |

**Returns:** `{return_type}`

**Example:**
```python
result = await registry.execute_tool("{name}", "{tool_name}", {example_params})
```

## Dependencies

- `{dependency}`

## Environment Variables

| Variable | Required | Description |
|----------|----------|-------------|
| `{ENV_VAR}` | {yes/no} | {description} |

## Error Handling

{error_handling_notes}
```

## Tool Schema Definition

Tool schemas follow the JSON Schema subset:

```python
ToolSchema = {
    "name": str,                    # Tool identifier (required)
    "description": str,             # Human-readable description (required)
    "parameters": {                 # Input parameters (optional)
        "type": "object",
        "properties": {
            "param_name": {
                "type": "string|integer|boolean|array|object",
                "description": str,
                "default": any,      # Optional default value
                "enum": [...],       # Optional allowed values
            }
        },
        "required": ["param_name"],  # Required parameter names
    },
    "returns": {                    # Return value (optional)
        "type": "string|object|array",
        "description": str,
    },
    "examples": [                   # Usage examples (optional)
        {
            "description": str,
            "arguments": {...},
            "result": ...
        }
    ],
    "token_count": int,             # Estimated token count
}
```

### Parameter Types

| Type | Python Equivalent | JSON Schema Type |
|------|-------------------|------------------|
| `string` | `str` | `string` |
| `integer` | `int` | `integer` |
| `number` | `float` | `number` |
| `boolean` | `bool` | `boolean` |
| `array` | `list` | `array` |
| `object` | `dict` | `object` |
| `null` | `None` | `null` |

### Tool Return Format

Tools should return a standardized result dictionary:

```python
{
    "success": bool,           # Whether the operation succeeded
    "output": any,             # Result data (if success=True)
    "error": str,              # Error message (if success=False)
    "metadata": {              # Optional execution metadata
        "execution_time": float,
        "token_count": int,
    }
}
```

## Implementation Requirements

### Base Class

Skills must inherit from `oclawma.skills.LazySkill`:

```python
from oclawma.skills import LazySkill, SkillMetadata

class MySkill(LazySkill):
    def __init__(self, metadata: SkillMetadata) -> None:
        super().__init__(metadata)
    
    def _load(self) -> None:
        """Initialize tools when first accessed."""
        self._tools = {
            "tool_name": self._tool_implementation,
        }
        self._loaded = True
    
    async def _tool_implementation(self, **params) -> dict:
        """Tool implementation."""
        try:
            # Do work
            return {
                "success": True,
                "output": result,
            }
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
            }
```

### __init__.py Entry Point

The package `__init__.py` should expose the skill class:

```python
"""OCLAWMA Skill: Example

{description}
"""

from .skill import MySkill

__version__ = "1.0.0"
__all__ = ["MySkill"]
```

## Complete Example

See `examples/skill-template/` for a complete working template.

## Discovery

OCLAWMA discovers pip-installed skills using entry points:

```python
from importlib.metadata import entry_points

eps = entry_points()
if 'oclawma.skills' in eps:
    for ep in eps['oclawma.skills']:
        skill_class = ep.load()
        # Register skill...
```

## Version Compatibility

| OCLAWMA Version | Skill API Version | Notes |
|-----------------|-------------------|-------|
| 0.1.x | 1.0 | Initial release |

## Publishing to PyPI

1. Build the package:
   ```bash
   python -m build
   ```

2. Upload to PyPI:
   ```bash
   python -m twine upload dist/*
   ```

3. Tag the release:
   ```bash
   git tag v1.0.0
   git push origin v1.0.0
   ```

## Best Practices

1. **Use semantic versioning** - Follow semver for version numbers
2. **Include comprehensive tests** - Test all tool implementations
3. **Document thoroughly** - Include examples in SKILL.md
4. **Handle errors gracefully** - Return structured error responses
5. **Minimize dependencies** - Only include necessary packages
6. **Cache token counts** - Provide accurate `token_count` estimates
7. **Support lazy loading** - Don't do heavy work until `_load()` is called
8. **Validate inputs** - Check parameters before execution
9. **Use type hints** - Add type annotations for clarity
10. **Include LICENSE** - Specify the license in your package

## FAQ

**Q: Can skills depend on other skills?**
A: Yes, add the skill package to your `requirements` in `pyproject.toml`.

**Q: Can I bundle multiple skills in one package?**
A: Yes, register multiple entry points in `pyproject.toml`.

**Q: What Python versions should I support?**
A: Match OCLAWMA's requirements (currently Python 3.9+).

**Q: Can skills include CLI commands?**
A: Yes, register additional entry points under `project.scripts`.

**Q: How do I test my skill?**
A: Use the `SkillRegistry` in your tests to load and execute tools.
