# Behavior-Bearing Packs

This design doc defines which runtime behavior surfaces packs already affect, which new executable surfaces are in scope for later work, and which trust gates must exist before any additional pack behavior ships.

!!! warning "Design-only lane"
    This page is the approved design output for [#1272](https://github.com/troylar/anteroom/issues/1272). It does not enable pack-executed hooks, pack-owned MCP server artifacts, or new pack artifact types.

## Why this doc exists

Packs already do more than ship static text. Today they can:

- register [skills](types/skill.md) that the user or model can invoke
- enforce hard [rules](types/rule.md) at tool time
- merge [config overlays](types/config-overlay.md) into the live config chain
- distribute [workflow templates](../workflows/definitions.md) and memory-scoped [policies](concepts.md#the-10-artifact-types)

At the same time, two adjacent surfaces remain intentionally incomplete:

- pack-sourced `hooks:` config is parsed but not executed
- `mcp_server` artifacts are stored but not loaded by the runtime MCP manager

This doc keeps those boundaries explicit and defines the next safe rollout shape.

## Current-State Matrix

| Surface | Declared via | Kind | Runtime status today | Conflict / trust model today |
|---|---|---|---|---|
| `skill` | Pack artifact | Executable | Loaded into the skill registry; user and model can invoke it | Existing artifact precedence applies; name collisions are resolved with namespace-qualified commands |
| `rule` | Pack artifact | Executable | Injected into prompt; `enforce: hard` rules can block tool calls | Additive across packs; hard safety remains non-bypassable |
| `config_overlay` | Pack artifact | Declarative | Merged into the live config chain for attached packs | Pack attachment priority decides overlaps; same-priority overlap is an attach-time error |
| `policy` | Pack artifact | Declarative | Merged through the overlay pipeline, but only for `memory.promotion.*` and `memory.retention.*` keys | Same priority model as `config_overlay`; non-allowlisted keys are dropped |
| `workflow_template` | Pack artifact | Executable | Discovered from `workflow_templates/*.yaml` under the pack source path | Filesystem workflows win on id collision; pack workflows do not silently replace built-ins |
| `mcp_server` | Pack artifact | Declarative | Stored in the artifact DB and visible as a pack artifact, but not consumed by `McpManager` | Additive as an artifact record only; no live trust or connection path yet |
| `hooks` | `hooks:` inside pack-contributed config | Executable candidate | Parsed into `HooksConfig` with `trust_source: "pack"`, then skipped by runtime dispatch | Personal > team > pack dedup still applies; pack hooks are intentionally non-executable |
| `mcp_servers` | `mcp_servers:` inside pack-contributed config | Declarative to executable | Merged into live config today because pack overlays merge normal config keys | Named-list config merge rules apply; this is a config-layer path, not `mcp_server` artifact loading |
| Separate `command` artifact | Not supported | N/A | No dedicated pack command type exists | Use `skill` for slash-command behavior today |
| Agent/runtime profiles | Not supported | N/A | No pack-owned sub-agent or runtime-profile surface exists | Deferred until the underlying runtime/profile model settles |

!!! info "Important distinction"
    `mcp_server` artifacts and `mcp_servers` config are not the same thing today. The artifact type is stored only. Live MCP connections come from the resolved config, which attached packs can already influence through `config_overlay`.

## Surface Decisions

The design makes each future surface explicit instead of implied.

| Surface | Decision | Reason |
|---|---|---|
| Hooks | Allow later | The hook runtime exists, but pack trust verification does not. This is the clearest next executable surface once trust and audit gates are ready |
| MCP declarations via `mcp_server` artifacts | Allow later | The artifact type already exists, but loading it directly into `McpManager` needs explicit trust, naming, and rollout rules |
| Separate `command` artifact type | Reject for now | Packs already have a user-facing command surface through `skill`. A second command model would duplicate invocation UX and conflict handling |
| Agent definitions / runtime profiles | Defer | The repo does not yet have a stable pack-owned agent profile model. This should not ship before the hook/runtime/approval semantics are settled |

## Trust Model

### Core rule

Installing or attaching a pack is **not** enough to grant executable trust.

Today, install + attach grants access to the existing pack surfaces that already participate in the runtime: skills, rules, overlays, policies, and workflow templates. Any future executable behavior surface must add a second trust gate.

### Trust granularity

Trust should be granted **per behavior surface**, not as a pack-wide blanket bit.

Why:

- packs already mix content, config, and executable behavior in one unit
- teams may want to trust a pack's rules and skills without trusting its hooks or MCP launches
- future remote refreshes should not silently upgrade a content pack into an executable one

Recommended trust buckets:

| Bucket | Examples | Default |
|---|---|---|
| Content / declarative | `instruction`, `context`, `memory`, `config_overlay`, `policy`, stored `mcp_server` artifact | Allowed under today's install + attach rules |
| Executable prompt behavior | `skill`, hard `rule`, `workflow_template` | Already shipped; keep existing behavior |
| Executable host behavior | Hook runners, live MCP process / SSE connection creation from pack-owned declarations | Disabled until explicitly trusted |

### Source-specific trust

Future executable trust should differ by how the pack entered the system.

| Source | Content surfaces | Future executable surfaces |
|---|---|---|
| Built-in pack shipped with Anteroom | Allowed | Eligible for release-managed allowlisting |
| Local manual install from disk | Allowed | Eligible for explicit local trust grant |
| Git-refreshed / remote pack source | Allowed | Must stay disabled until the exact source ref is approved |

### Versioning and rollout

Executable trust should bind to a concrete pack version and source ref, not just `namespace/name`.

That means:

- the lock file remains the baseline record for what was installed
- future executable approvals should also record the approved source ref
- when a pack refresh changes the source ref, executable surfaces should fall back to disabled or pending re-approval

## Non-Bypassable Safety Rules

Nothing in a behavior-bearing pack may weaken the hard safety floor from [#1265](https://github.com/troylar/anteroom/issues/1265).

Non-bypassable invariants:

- hard rule-enforcer denies still win before hook logic
- `safety.denied_tools`, `read_only`, and equivalent hard blocks remain authoritative
- team-enforced config fields remain authoritative after pack overlay merge
- a pack hook or MCP declaration may request stricter behavior, but not a more permissive safety floor than the resolved config allows

## Conflict Model

Existing pack precedence stays in place for current artifact surfaces:

- artifact precedence remains `inline > local > project(pack) > team > global > built_in`
- pack attachment priority continues to resolve `config_overlay` and `policy` overlap
- skill name collisions stay namespace-qualified rather than attach-time errors

Future executable surfaces should use explicit attach-time conflict rules instead of silent override.

| Surface | Proposed rule |
|---|---|
| Hook `id` | Duplicate ids across attached packs are an attach-time error. Personal and team hooks still outrank packs because they are separate config layers |
| Pack-owned MCP server name | Duplicate live server names across attached packs are an attach-time error unless a later design introduces an explicit namespacing scheme |
| Agent/runtime profile id | If introduced later, ids must be namespace-qualified and duplicate active ids should be an attach-time error |
| Separate command artifact | Not applicable because this design rejects a second command surface |

Priority should remain for declarative overlays. Identity-bearing executable surfaces should fail fast on ambiguity.

## Phased Rollout

### Phase 0: Docs and current-state cleanup

Ship now in this issue:

- document the current runtime truth
- keep pack hooks non-executable
- keep `mcp_server` artifacts stored-only
- make the dependency on [#1271](https://github.com/troylar/anteroom/issues/1271) explicit

### Phase 1: Trusted pack hooks

Only after the hook runtime, audit, and approval semantics are stable:

- introduce an explicit trust grant for pack-owned hooks
- bind the trust grant to pack version / source ref
- keep server-mode trust admin-controlled, not prompt-driven

### Phase 2: Trusted pack-owned MCP declarations

Only after the trust model above exists:

- decide whether `mcp_server` artifacts become the canonical pack-owned MCP surface
- require explicit approval before a pack can launch local processes or connect remote MCP endpoints
- keep `config_overlay`-based `mcp_servers` behavior documented as current runtime truth, but do not treat it as the long-term executable-pack API

### Phase 3: Revisit agent/runtime profiles

Do this only if the repo lands a stable profile model worth distributing by pack. It should be a separate design and implementation track, not folded into hook or MCP work by implication.

## Non-Goals

This design does not:

- invent a new marketplace or signing protocol
- add a new command artifact type
- change current artifact precedence
- expand `policy` beyond the current memory-only allowlist
- treat this issue as approval to ship executable pack behavior immediately

## Follow-Up Work

If this design is accepted, follow-up issues should stay narrow:

1. trust record and re-approval model for executable pack surfaces
2. trusted pack hook execution
3. trusted pack-owned MCP declaration loading
4. any later agent/runtime profile design as a separate issue
