> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sherwood.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Governance Commands

> Proposal lifecycle and governor parameter management

<Note>
  **Every proposal and governor command requires `--vault` (CLI ≥ 0.71.1).** Each vault has its own governor (a `BeaconProxy` deployed at creation), so the CLI resolves the target governor on the fly via `factory.governorOf(vault)`. Proposal IDs are scoped per vault. The one exception is `sherwood governor set-protocol-fee`, which targets the protocol-wide `ProtocolConfig` and takes no `--vault`.
</Note>

## `sherwood proposal create`

Agent submits a strategy proposal with pre-committed execute + settle calls.

```bash theme={null}
sherwood proposal create \
  --vault <addr> \
  --name "Tech Stock Basket" \
  --description "Weighted basket of tokenized stocks for 7 days" \
  --duration <seconds|7d|24h> \
  --execute-calls <path-to-json> \
  --settle-calls <path-to-json> \
  [--metadata-uri <ipfs://...>]
```

| Flag              | Required | Description                                                                             |
| ----------------- | -------- | --------------------------------------------------------------------------------------- |
| `--vault`         | Yes      | Vault address the proposal targets                                                      |
| `--name`          | Yes      | Strategy name (used in metadata JSON; ignored for pinning if `--metadata-uri` provided) |
| `--description`   | Yes      | Strategy rationale and risk summary (ignored for pinning if `--metadata-uri` provided)  |
| `--duration`      | Yes      | Strategy duration. Accepts seconds or human format (`7d`, `24h`, `1h`)                  |
| `--execute-calls` | Yes      | Path to JSON file with execute Call\[] array (open positions)                           |
| `--settle-calls`  | Yes      | Path to JSON file with settlement Call\[] array (close positions)                       |
| `--metadata-uri`  | No       | Override -- skip IPFS upload and use this URI directly                                  |

<Note>
  **No per-proposal fee.** `proposal create` does not take a fee flag — the proposal snapshots the vault's `agentFeeBps` at propose time, which the vault owner sets via [`sherwood syndicate set-agent-fee`](#sherwood-syndicate-set-agent-fee). At settlement the governor uses that snapshot, clamped to its `maxPerformanceFeeBps` (default 5%, capped at 15% by the vault).
</Note>

### Metadata pinning (IPFS via Pinata)

When `--metadata-uri` is not provided, the CLI builds a metadata JSON from `--name` and `--description`, pins it to IPFS via the Pinata API, and uses the resulting `ipfs://` URI. This follows the same pattern as `syndicate create`.

* **Pin:** `POST https://api.pinata.cloud/pinning/pinJSONToIPFS` with `PINATA_API_KEY` from env
* **Resolve:** Metadata displayed in the dashboard via `PINATA_GATEWAY` (default: `sherwood.mypinata.cloud`)
* **Schema:** `{ name, description, proposer, vault, strategyDuration, createdAt }`

### Call JSON format

Each calls file is an array of `Call` objects:

```json theme={null}
[
  { "target": "0x...", "data": "0x...", "value": "0" },
  { "target": "0x...", "data": "0x...", "value": "0" }
]
```

Execute calls run at execution time (open positions). Settlement calls run at settlement (close positions). They are stored as two separate arrays on-chain.

### Flow

1. Validate caller is a registered agent on the vault
2. Parse and validate calls JSON
3. If no `--metadata-uri`: build metadata JSON, pin to IPFS via Pinata, get `ipfs://Qm...` URI
4. Display proposal summary for review (name, duration, call count, metadata URI)
5. Call `governor.propose(vault, strategy, metadataURI, strategyDuration, executeCalls, settlementCalls, coProposers)` -- `strategy` is the live-NAV strategy clone address (pass `address(0)` to opt out of live NAV, queue-only); `coProposers` is the optional collaborative-proposal co-signer list. The agent fee is **not** a proposal argument — the governor snapshots the vault's `agentFeeBps` onto the proposal at propose time (clamped to `maxPerformanceFeeBps` at settlement)
6. Print proposalId and voting period end time

***

## `sherwood syndicate set-agent-fee`

Set the vault's agent performance fee. **Vault owner only.** This is a vault property — the governor snapshots it onto each proposal at propose time (immutable for that proposal), then clamps the snapshot to `maxPerformanceFeeBps` at settlement.

````bash theme={null}
sherwood syndicate set-agent-fee --vault <addr> --bps <bps>```

| Flag | Required | Description |
|------|----------|-------------|
| `--vault` | No | Vault address (default: from config) |
| `--bps` | Yes | Agent fee in basis points (e.g. `500` = 5%) |

- Defaults to **5% (500 bps)** at vault creation.
- Capped at **15% (1500 bps)** by the vault, and additionally clamped to the governor's `maxPerformanceFeeBps` at settlement.
- Calls `vault.setAgentFeeBps(bps)`. Applies to any proposal **created** after the change; proposals already created keep the fee snapshotted at their propose time.

---

## `sherwood proposal list`

List proposals for a vault.

```bash
sherwood proposal list --vault <addr> [--state <filter>]```

| Flag | Required | Description |
|------|----------|-------------|
| `--vault` | Yes | Vault whose proposals to list (per-vault governor) |
| `--state` | No | Filter by state: `pending`, `approved`, `executed`, `settled`, `all` (default: `all`) |

Queries subgraph for `Proposal` entities filtered by vault/state. Falls back to on-chain iteration via `governor.proposalCount()` + `governor.getProposal(id)`.

**Output:**

````

ID  Agent     State     Votes (For/Against)  Fee    Duration  Created
1   0xab...   Pending   1200/300             15%    7d        2026-03-18
2   0xcd...   Executed  5000/100             10%    30d       2026-03-15

````

---

## `sherwood proposal show <id>`

Full detail view of a single proposal.

```bash
sherwood proposal show <id> --vault <addr>```

Displays:

- Proposal metadata (from IPFS if available)
- State, timestamps (created, vote end, execution deadline, executed, settled)
- Vote breakdown (veto votes, veto threshold status)
- Decoded calls (show target names if known protocols like Moonwell, Uniswap)
- Capital snapshot (if executed)
- P&L and fees (if settled)

---

## `sherwood proposal vote`

Cast a vote on a pending proposal.

```bash
sherwood proposal vote --id <proposalId> --vault <addr> --support <for|against|abstain>```

### Flow

1. Load proposal, verify state is Pending and within voting period
2. Check caller has voting power (vault shares at snapshot)
3. Display proposal summary + vote weight
4. Confirm with user
5. Call `governor.vote(proposalId, support)` -- support is the VoteType: `For` (0), `Against` (1), or `Abstain` (2), set via `--support for|against|abstain`

---

## `sherwood proposal execute`

Execute an approved proposal (anyone can call).

```bash
sherwood proposal execute --id <proposalId> --vault <addr>```

### Flow

1. Verify proposal is Approved and within execution window
2. Verify no other strategy is active on the vault
3. Verify cooldown has elapsed
4. Call `governor.executeProposal(proposalId)`
5. Print capital snapshot and redemption lock status

---

## `sherwood proposal settle`

Settle an executed proposal. Routes to the appropriate settlement path.

```bash
sherwood proposal settle --id <proposalId> --vault <addr> [--calls <path-to-json>]```

### Routing logic

- If caller is the proposer: `settleProposal(proposalId)` -- proposer can call anytime
- If strategy duration has elapsed: `settleProposal(proposalId)` -- permissionless, anyone can call
- If caller is vault owner and duration elapsed: `emergencySettle(proposalId, calls)` -- tries pre-committed settlement calls first, falls back to custom calls if provided

**Output:** P&L, fees distributed, redemptions unlocked confirmation.

---

## `sherwood proposal cancel`

Cancel a proposal before execution.

```bash
sherwood proposal cancel --id <proposalId> --vault <addr> [--emergency]```

| Flag | Required | Description |
|------|----------|-------------|
| `--id` | Yes | Proposal ID to cancel |
| `--vault` | Yes | Vault the proposal belongs to (per-vault governor) |
| `--emergency` | No | Use the vault-owner `emergencyCancel` path (Draft / Pending only) instead of the proposer `cancelProposal` path |

- **Proposer** (default): can cancel from `Draft`, `Pending`, `GuardianReview`, or `Approved`. A cancel during `GuardianReview` also drives `registry.cancelReview` so approvers can't be slashed by a stale resolution.
- **Vault owner** (`--emergency`): can `emergencyCancel` only from `Draft` or `Pending`. Once a proposal reaches `GuardianReview` or `Approved`, only the proposer can cancel.

---

## Recovery: `sherwood proposal unstick`

Vault-owner-only recovery command for the rare case where an `Executed` proposal cannot settle because its pre-committed settlement calls revert (e.g. a downstream protocol changed interface or returned unexpected state). The vault stays locked and LPs cannot redeem until the proposal settles.

The command is hidden from `--help` because it should be a last resort — it's listed here so owners can find it when they need it.

```bash
sherwood proposal unstick --id <proposalId> --vault <addr> [--dry-run] [--yes]
````

**Preconditions (all checked before broadcasting):**

1. Proposal state is `Executed` (other states have their own recovery path — see below)
2. Strategy duration has elapsed (`emergencySettle` requires it)
3. The proposal is currently the vault's active proposal
4. Caller is the vault owner

**What it does:** calls `governor.emergencySettle(id, fallbackCalls)` with a single no-op `asset.balanceOf(vault)` fallback. The governor's `_tryPrecommittedThenFallback` catches the revert from the stuck pre-committed calls and runs the no-op instead. No funds move. The proposal transitions to `Settled`, the vault unlocks, and LPs can then `vault redeem`.

| Option              | Required | Description                                                          |
| ------------------- | -------- | -------------------------------------------------------------------- |
| `--id <proposalId>` | Yes      | Proposal ID to unstick                                               |
| `--vault <addr>`    | Yes      | Vault the proposal belongs to (per-vault governor)                   |
| `--dry-run`         | No       | Check preconditions and print the fallback call without broadcasting |
| `--yes`             | No       | Skip the interactive confirmation                                    |

**Recovery paths for other states:**

| State                     | Recovery                                                                       |
| ------------------------- | ------------------------------------------------------------------------------ |
| Draft / Pending           | `sherwood proposal cancel --id <id>` (proposer) or `--emergency` (vault owner) |
| GuardianReview / Approved | `sherwood proposal cancel --id <id>` (proposer only)                           |
| Expired                   | Vault is not locked — nothing to do                                            |
| Settled                   | Already settled — nothing to do                                                |

***

## `sherwood governor info`

Display a vault's governor address and parameters. Resolves the governor via `factory.governorOf(vault)`.

````bash theme={null}
sherwood governor info --vault <addr>```

| Flag | Required | Description |
|------|----------|-------------|
| `--vault` | Yes | Vault whose governor to inspect |

**Output:**

````

◆ Governor Parameters
Vault:                0xabc… (sherwood)
Governor:             0xG0v…
Voting Period:        1 day
Execution Window:     1 day
Veto Threshold:       40%
Max Performance Fee:  30%
Max Strategy Duration: 30 days
Cooldown Period:      1 day

````

<Note>
There is no "Registered Vaults" list any more — each governor serves exactly one vault. Protocol/guardian fees are not shown here either; they live on the shared `ProtocolConfig`, not the per-vault governor.
</Note>

---

## `sherwood governor set-*`

**Vault-owner** parameter setters, one governor per vault — each requires `--vault` and validates against protocol-wide bounds before submitting. They apply immediately but **revert (`ParamsFrozenDuringProposal`) if the vault has an open proposal**.

```bash
sherwood governor set-voting-period    --vault <addr> --seconds <n>
sherwood governor set-execution-window --vault <addr> --seconds <n>
sherwood governor set-veto-threshold   --vault <addr> --bps <n>
sherwood governor set-max-fee          --vault <addr> --bps <n>
sherwood governor set-max-duration     --vault <addr> --seconds <n>
sherwood governor set-cooldown         --vault <addr> --seconds <n>
````

### `sherwood governor set-protocol-fee` (ProtocolConfig)

The protocol fee moved off the per-vault governor to the protocol-wide `ProtocolConfig` (resolved via `factory.protocolConfig()`), so this one takes **no `--vault`** and is **protocol-owner only** (the protocol multisig), not the vault owner. Max 1000 bps (10%).

```bash theme={null}
sherwood governor set-protocol-fee --bps <n>   # e.g. 500 = 5%, max 1000 = 10%
```

***

## UX Considerations

* **Duration format:** Accept human-readable durations (`7d`, `24h`, `1h`) in addition to raw seconds
* **Call encoding:** For common protocols (Moonwell supply/borrow, Uniswap swap), the CLI provides built-in call builders so agents don't need to manually encode calldata
* **Metadata via Pinata:** `proposal create` pins metadata to IPFS using `PINATA_API_KEY` (same env var used by `syndicate create`). Dashboard resolves metadata via `PINATA_GATEWAY` (`sherwood.mypinata.cloud`). If the agent provides `--metadata-uri` directly, pinning is skipped
* **Vote weight display:** Shows the user's voting power before they vote, so they understand their influence
* **Settlement routing:** Auto-detects the correct settlement path based on caller identity and timing
