# Beaver Skill Plugins

Declarative skill plugins let an operator mirror skills from a local plugin package into Beaver's managed skill lifecycle. V1 plugins are data packages only: Beaver reads manifests and skill files, but it does not execute plugin Python code, install dependencies, or run arbitrary hooks.

## Package Layout

A plugin package is a directory containing `beaver.plugin.json` and one or more skill directories:

```text
my-plugin/
  beaver.plugin.json
  skills/
    my-skill/
      SKILL.md
      templates/
        example.md
```

Manifest example:

```json
{
  "schema_version": 1,
  "id": "my-plugin",
  "name": "My Plugin",
  "version": "1.0.0",
  "skills": [
    { "name": "my-skill", "path": "skills/my-skill" }
  ]
}
```

IDs and skill names use lowercase identifiers with letters, digits, `_`, and `-`. Skill paths must stay inside the plugin package, cannot use symlinks, and must contain a regular `SKILL.md`.

## Discovery

Beaver discovers plugin manifests from:

- the workspace `plugins/` directory;
- configured `plugins.search_paths` entries in Beaver config.

Discovery only records available packages. Operators must explicitly enable a plugin before its skills are mirrored.

## Mirroring

When a plugin is enabled, Beaver stages immutable upstream snapshots, safety-checks every declared skill, then publishes each mirrored skill as a normal workspace skill version. The first mirror becomes `v0001` and carries plugin provenance:

- `source_kind: plugin`;
- plugin id and plugin version;
- upstream content hash;
- upstream full-tree hash.

If a skill with the same name already exists and is not plugin-owned, enable fails without publishing any plugin skill.

## Hashing And Supporting Files

Beaver tracks two hashes:

- content hash: normalized `SKILL.md` content;
- tree hash: `SKILL.md` plus supporting files, relative paths, sizes, bytes, and executable-bit state.

Mtime, owner, group, and non-executable mode bits do not affect the tree hash. Beaver metadata files such as `version.json` and `upstream.json` are excluded.

Supporting files are copied into Beaver-managed skill versions. Local revisions inherit supporting files from their base version; uploaded supporting files can override inherited files. Plugin update drafts copy supporting files from the referenced upstream snapshot when published. Divergent supporting-file edits are blocked by the publish gate until resolved.

## Upgrade Flow

When an enabled plugin version changes, sync compares:

- accepted upstream tree;
- current Beaver skill tree;
- newly discovered upstream tree.

Possible outcomes:

- unchanged: no candidate;
- already applied: state is reconciled without a draft;
- fast forward: Beaver creates a `plugin_skill_update` candidate that can draft the exact upstream content without an LLM;
- three-way: Beaver creates a `plugin_skill_update` candidate using old upstream, current local, and new upstream inputs.

Plugin update candidates go through the same draft, safety, replay evaluation, review, publish, and rollback flow as learned skills. Three-way plugin updates require a plugin preservation report showing local and upstream sections were preserved and conflicts were resolved.

## Lifecycle Controls

Pause and resume affect updates only. Paused plugins keep current mirrored skills active and suppress new update candidates until resumed.

Disable requires explicit confirmation to disable linked skills. It disables the plugin and its linked Beaver skills, but keeps historical versions on disk.

Adopt detaches a mirrored skill from the plugin and keeps the skill active as a managed Beaver skill. Future plugin updates no longer apply to that skill.

## Recovery

If a previously enabled plugin package is removed or becomes undiscoverable, sync marks the plugin `missing`. Current Beaver skills remain active; updates are suspended until the package returns or the operator disables/adopts the skills.

If publication succeeds but the plugin state acknowledgement fails, the next sync reconciles state from the published draft provenance and clears the pending candidate.

Workspace writes are serialized by the shared workspace write lock. Boot-time auto-sync uses the same lock and defers safely if another writer is active.

## V1 Boundary

V1 does not execute plugin code. This keeps install and sync deterministic, avoids dependency side effects, and leaves tool execution to Beaver's existing MCP/tool runtime.
