# Skill Context & Registry

Runtime context and registry for skill execution in CleverAgents v3.

## SkillContext

The `SkillContext` class provides the runtime environment for skill
execution.  It carries plan/project identifiers, a sandbox root path,
resource bindings, and a change tracker for recording tool invocations.

### Fields

| Field | Type | Description |
|-------|------|-------------|
| `plan_id` | `str` | Identifier for the current plan |
| `project_id` | `str` | Identifier for the current project |
| `sandbox_path` | `Path` | Root path to the execution sandbox |
| `change_tracker` | `list[dict]` | Recorded tool invocation records |
| `resource_bindings` | `dict[str, Any]` | Bound resource name → value mapping |
| `read_only` | `bool` | Whether write operations are forbidden |
| `metadata` | `dict[str, Any]` | Arbitrary plan/project metadata |

### Methods

#### `resolve_resource(name: str) -> Any`

Look up a bound resource by name from `resource_bindings`.  Raises
`SkillError(RESOLUTION_FAILURE)` if the resource is not found.

#### `get_plan_metadata() -> dict[str, Any]`

Return a dict containing `plan_id`, `project_id`, and any additional
metadata stored on the context.

#### `get_sandbox_path() -> Path`

Return the sandbox root `Path`.

#### `is_read_only() -> bool`

Check whether this context forbids write operations.

#### `register_tool_invocation(tool_name, input_data, output_data, duration_ms)`

Record a tool invocation in the change tracker.  Each record stores
the tool name, input/output data, duration, plan ID, and project ID.

#### `enforce_write_guard(tool_name: str)`

Raise `SkillError(PERMISSION_DENIED)` if the context is read-only and
a tool attempts to write.  Should be called before any write operation.

## SkillRegistry

The `SkillRegistry` class manages in-memory registration and lookup of
skill definitions.

### Constructor

```python
SkillRegistry(tool_registry=None)
```

Optionally accepts a reference to a Tool Registry service for
tool-ref validation.

### Methods

#### `register(skill: SkillDefinition)`

Register a skill definition.  Raises `SkillError(VALIDATION_ERROR)` if
a skill with the same name is already registered.

#### `unregister(name: str)`

Remove a skill from the registry.  Raises `SkillError(SKILL_NOT_FOUND)`
if the skill is not registered.

#### `get(name: str) -> SkillDefinition`

Look up a skill by name.  Raises `SkillError(SKILL_NOT_FOUND)` if not
found.

#### `list_all() -> list[SkillMetadata]`

Return metadata for all registered skills, sorted by name.

#### `resolve_tools(skill_name: str) -> list[ResolvedToolEntry]`

Resolve tool references for a registered skill using the
`SkillResolver`.

#### `validate_skill(skill: SkillDefinition) -> list[str]`

Validate tool references exist in the tool registry, inline tools have
descriptions, and included skills are registered.  Returns a list of
error messages (empty means valid).
