# Rule reference

> Every change MCP Inspect can report, with its default severity and what to do about it. Generated from the diff engine, so it cannot drift.

Each rule has a stable id. `.mcp-inspect.yml` silences by id, the JSON and
SARIF reports carry it, and every heading on this page is a link target — so
an annotation in your CI can point straight at the rule that produced it.

Renaming a rule would break customers' configs, so a classification change
adds a new id and keeps the old one emitting until a major version.

```yaml
# .mcp-inspect.yml
ignore:
  - rule: tool.icons.changed
  - rule: tool.description.changed
    entity: legacy_*
    reason: "Legacy tools are being rewritten; churn is expected."

severity_overrides:
  tool.annotations.safetyWeakened: BREAKING
```

## Index

**Server and protocol** — [`server.capability.added`](#server.capability.added) · [`server.capability.changed`](#server.capability.changed) · [`server.capability.removed`](#server.capability.removed) · [`server.extension.added`](#server.extension.added) · [`server.extension.changed`](#server.extension.changed) · [`server.extension.removed`](#server.extension.removed) · [`server.identity.changed`](#server.identity.changed) · [`server.instructions.changed`](#server.instructions.changed) · [`server.protocolVersion.changed`](#server.protocolVersion.changed) · [`server.surface.scopeNarrowed`](#server.surface.scopeNarrowed) · [`server.version.added`](#server.version.added) · [`server.version.dropped`](#server.version.dropped)

**Tool input schemas** — [`tool.input.added`](#tool.input.added) · [`tool.input.constraint.changed`](#tool.input.constraint.changed) · [`tool.input.constraint.loosened`](#tool.input.constraint.loosened) · [`tool.input.constraint.tightened`](#tool.input.constraint.tightened) · [`tool.input.default.changed`](#tool.input.default.changed) · [`tool.input.deprecated.added`](#tool.input.deprecated.added) · [`tool.input.deprecated.removed`](#tool.input.deprecated.removed) · [`tool.input.description.changed`](#tool.input.description.changed) · [`tool.input.enum.narrowed`](#tool.input.enum.narrowed) · [`tool.input.enum.widened`](#tool.input.enum.widened) · [`tool.input.header.changed`](#tool.input.header.changed) · [`tool.input.property.added`](#tool.input.property.added) · [`tool.input.property.addedRequired`](#tool.input.property.addedRequired) · [`tool.input.property.removed`](#tool.input.property.removed) · [`tool.input.removed`](#tool.input.removed) · [`tool.input.required.added`](#tool.input.required.added) · [`tool.input.required.removed`](#tool.input.required.removed) · [`tool.input.schema.changed`](#tool.input.schema.changed) · [`tool.input.type.changed`](#tool.input.type.changed) · [`tool.input.type.narrowed`](#tool.input.type.narrowed) · [`tool.input.type.widened`](#tool.input.type.widened)

**Tool output schemas** — [`tool.output.added`](#tool.output.added) · [`tool.output.constraint.changed`](#tool.output.constraint.changed) · [`tool.output.constraint.loosened`](#tool.output.constraint.loosened) · [`tool.output.constraint.tightened`](#tool.output.constraint.tightened) · [`tool.output.default.changed`](#tool.output.default.changed) · [`tool.output.deprecated.added`](#tool.output.deprecated.added) · [`tool.output.deprecated.removed`](#tool.output.deprecated.removed) · [`tool.output.description.changed`](#tool.output.description.changed) · [`tool.output.enum.narrowed`](#tool.output.enum.narrowed) · [`tool.output.enum.widened`](#tool.output.enum.widened) · [`tool.output.header.changed`](#tool.output.header.changed) · [`tool.output.property.added`](#tool.output.property.added) · [`tool.output.property.addedRequired`](#tool.output.property.addedRequired) · [`tool.output.property.removed`](#tool.output.property.removed) · [`tool.output.removed`](#tool.output.removed) · [`tool.output.required.added`](#tool.output.required.added) · [`tool.output.required.removed`](#tool.output.required.removed) · [`tool.output.schema.changed`](#tool.output.schema.changed) · [`tool.output.type.changed`](#tool.output.type.changed) · [`tool.output.type.narrowed`](#tool.output.type.narrowed) · [`tool.output.type.widened`](#tool.output.type.widened)

**Tools** — [`tool.added`](#tool.added) · [`tool.annotations.added`](#tool.annotations.added) · [`tool.annotations.changed`](#tool.annotations.changed) · [`tool.annotations.removed`](#tool.annotations.removed) · [`tool.annotations.safetyWeakened`](#tool.annotations.safetyWeakened) · [`tool.description.changed`](#tool.description.changed) · [`tool.icons.changed`](#tool.icons.changed) · [`tool.meta.changed`](#tool.meta.changed) · [`tool.removed`](#tool.removed) · [`tool.renamed`](#tool.renamed) · [`tool.title.changed`](#tool.title.changed) · [`tool.ui.resourceUri.added`](#tool.ui.resourceUri.added) · [`tool.ui.resourceUri.changed`](#tool.ui.resourceUri.changed) · [`tool.ui.resourceUri.removed`](#tool.ui.resourceUri.removed) · [`tool.ui.visibility.narrowed`](#tool.ui.visibility.narrowed) · [`tool.ui.visibility.widened`](#tool.ui.visibility.widened)

**Resource templates** — [`resourceTemplate.added`](#resourceTemplate.added) · [`resourceTemplate.annotations.changed`](#resourceTemplate.annotations.changed) · [`resourceTemplate.description.changed`](#resourceTemplate.description.changed) · [`resourceTemplate.meta.changed`](#resourceTemplate.meta.changed) · [`resourceTemplate.mimeType.changed`](#resourceTemplate.mimeType.changed) · [`resourceTemplate.name.changed`](#resourceTemplate.name.changed) · [`resourceTemplate.removed`](#resourceTemplate.removed) · [`resourceTemplate.title.changed`](#resourceTemplate.title.changed)

**Resources** — [`resource.added`](#resource.added) · [`resource.annotations.changed`](#resource.annotations.changed) · [`resource.description.changed`](#resource.description.changed) · [`resource.meta.changed`](#resource.meta.changed) · [`resource.mimeType.changed`](#resource.mimeType.changed) · [`resource.name.changed`](#resource.name.changed) · [`resource.removed`](#resource.removed) · [`resource.title.changed`](#resource.title.changed) · [`resource.ui.csp.narrowed`](#resource.ui.csp.narrowed) · [`resource.ui.csp.widened`](#resource.ui.csp.widened) · [`resource.ui.domain.changed`](#resource.ui.domain.changed) · [`resource.ui.permissions.added`](#resource.ui.permissions.added) · [`resource.ui.permissions.removed`](#resource.ui.permissions.removed) · [`resource.ui.widgetDescription.changed`](#resource.ui.widgetDescription.changed)

**Prompts** — [`prompt.added`](#prompt.added) · [`prompt.argument.added`](#prompt.argument.added) · [`prompt.argument.addedRequired`](#prompt.argument.addedRequired) · [`prompt.argument.description.changed`](#prompt.argument.description.changed) · [`prompt.argument.nowOptional`](#prompt.argument.nowOptional) · [`prompt.argument.nowRequired`](#prompt.argument.nowRequired) · [`prompt.argument.removed`](#prompt.argument.removed) · [`prompt.description.changed`](#prompt.description.changed) · [`prompt.removed`](#prompt.removed) · [`prompt.title.changed`](#prompt.title.changed)

## Server and protocol

### server.capability.added

**Default severity:** `NON_BREAKING`

A capability is now advertised.

### server.capability.changed

**Default severity:** `POTENTIALLY_BREAKING`

e.g. `listChanged` or `subscribe` flipped.

> [!NOTE]
> Check that clients relying on the previous flag still behave correctly.

### server.capability.removed

**Default severity:** `BREAKING`

`capabilities.tools` / `resources` / `prompts` / … withdrawn.

> [!NOTE]
> Clients gate whole feature sets on this capability. Restore it, or announce the removal a release ahead.

### server.extension.added

**Default severity:** `NON_BREAKING`

A new extension is advertised.

### server.extension.changed

**Default severity:** `POTENTIALLY_BREAKING`

An extension's settings object changed.

> [!NOTE]
> Extension settings are part of the negotiated contract; version the extension id if this is not backwards compatible.

### server.extension.removed

**Default severity:** `BREAKING`

An advertised extension is gone; clients negotiated for it.

> [!NOTE]
> A client that negotiated this extension will lose the behaviour it asked for. Restore it, or fall back to core behaviour explicitly.

### server.identity.changed

**Default severity:** `DOCUMENTATION`

`serverInfo.name` / `version` / `title` changed.

### server.instructions.changed

**Default severity:** `DOCUMENTATION` or `POTENTIALLY_BREAKING`

The `instructions` string changed. It is in the model's context.

> [!NOTE]
> Instructions are in the model's context on every conversation. Re-run any evaluation that depends on how this server is used.

### server.protocolVersion.changed

**Default severity:** `POTENTIALLY_BREAKING`

The negotiated revision changed. Different rules now apply.

> [!NOTE]
> Confirm clients on the previous revision can still reach this server, and keep the old version in supportedVersions until they have moved.

### server.surface.scopeNarrowed

**Default severity:** `POTENTIALLY_BREAKING`

A list result went `cacheScope: public` → `private`: the surface now varies by authorization, so this snapshot describes one caller's view, not the server's.

> [!NOTE]
> This surface now varies by authorization, so a snapshot describes one caller's view. Capture baselines with a consistent credential or this diff will report phantom changes.

### server.version.added

**Default severity:** `NON_BREAKING`

A new protocol version is supported.

### server.version.dropped

**Default severity:** `BREAKING`

A previously supported protocol version is gone.

> [!NOTE]
> Restore the version, or confirm no client still negotiates it.

## Tool input schemas

### tool.input.added

**Default severity:** `NON_BREAKING`

An absent `outputSchema` appeared.

### tool.input.constraint.changed

**Default severity:** `BREAKING`

`pattern`, `format`, `const`, `multipleOf`, `$ref` or a `oneOf` branch set changed: not orderable.

> [!NOTE]
> The two constraints are not orderable, so compatibility cannot be established structurally. Verify by hand.

### tool.input.constraint.loosened

**Default severity:** `NON_BREAKING`

A bound moved outward.

> [!NOTE]
> Consumers validating results against the old bound will start rejecting them.

### tool.input.constraint.tightened

**Default severity:** `BREAKING`

A bound moved inward (`minLength`, `maximum`, `additionalProperties: false`, `uniqueItems`, `allOf` branch added, `anyOf` branch removed).

> [!NOTE]
> Input that was valid is now rejected. Loosen the bound, or stage the change.

### tool.input.default.changed

**Default severity:** `POTENTIALLY_BREAKING`

A `default` was added, removed or changed. The schema still validates; the behavior does not match.

> [!NOTE]
> The schema still validates, but calls that omit this argument now behave differently. Check telemetry for how often it is omitted before shipping.

### tool.input.deprecated.added

**Default severity:** `NON_BREAKING`

`deprecated: true` appeared on a property.

> [!NOTE]
> Check usage before removing it in a later release.

### tool.input.deprecated.removed

**Default severity:** `NON_BREAKING`

A property is no longer marked deprecated.

### tool.input.description.changed

**Default severity:** `DOCUMENTATION` or `POTENTIALLY_BREAKING`

A property `description` **or** `title` changed. Models read these when filling arguments.

> [!NOTE]
> Models read property descriptions when filling arguments. A changed one can change what gets passed.

### tool.input.enum.narrowed

**Default severity:** `BREAKING`

Values removed from an `enum`.

> [!NOTE]
> Callers passing a removed value will now fail. Accept the old values and map them for one release.

### tool.input.enum.widened

**Default severity:** `NON_BREAKING`

Values added to an `enum`.

> [!NOTE]
> Consumers switching exhaustively on this enum will not handle the new values.

### tool.input.header.changed

**Default severity:** `BREAKING`

`x-mcp-header` added, removed or changed: it alters how the call is transmitted over HTTP.

> [!NOTE]
> x-mcp-header changes how the call is transmitted over HTTP, so intermediaries routing on the mirrored header will stop matching.

### tool.input.property.added

**Default severity:** `NON_BREAKING`

A new optional property.

### tool.input.property.addedRequired

**Default severity:** `BREAKING`

A new property that is immediately required.

> [!NOTE]
> Every existing call omits this property and will now fail validation. Add it as optional with a default, then require it a release later.

### tool.input.property.removed

**Default severity:** `BREAKING`

A property is gone.

> [!NOTE]
> Accept and ignore the property for one release so existing callers keep working, then remove it.

### tool.input.removed

**Default severity:** `BREAKING`

A declared `outputSchema` disappeared.

> [!NOTE]
> A client that generated types from this schema loses them. Restore the schema, or release the removal as a major version.

### tool.input.required.added

**Default severity:** `BREAKING`

Optional → required.

> [!NOTE]
> Accept calls that omit it for at least one release, applying the previous default, then require it.

### tool.input.required.removed

**Default severity:** `NON_BREAKING`

Required → optional.

> [!NOTE]
> Consumers may assume this field is always present in a result. Keep emitting it, or release the change as a major version.

### tool.input.schema.changed

**Default severity:** `BREAKING`

**The completeness net.** A difference the structured walk does not model. See §9.

> [!NOTE]
> This schema keyword is not modelled by the diff engine, so the change is reported as breaking until a human confirms otherwise.

### tool.input.type.changed

**Default severity:** `BREAKING`

Type sets are not comparable.

> [!NOTE]
> The type sets are not comparable, so no existing caller is guaranteed to still work.

### tool.input.type.narrowed

**Default severity:** `BREAKING`

The `type` set shrank.

> [!NOTE]
> Keep accepting the removed types and coerce them for one release.

### tool.input.type.widened

**Default severity:** `NON_BREAKING`

The `type` set grew.

> [!NOTE]
> Consumers typed against the narrower schema will not handle the new types.

## Tool output schemas

### tool.output.added

**Default severity:** `NON_BREAKING`

An absent `outputSchema` appeared.

### tool.output.constraint.changed

**Default severity:** `BREAKING`

`pattern`, `format`, `const`, `multipleOf`, `$ref` or a `oneOf` branch set changed: not orderable.

> [!NOTE]
> The two constraints are not orderable, so compatibility cannot be established structurally. Verify by hand.

### tool.output.constraint.loosened

**Default severity:** `BREAKING`

A bound moved outward.

> [!NOTE]
> Consumers validating results against the old bound will start rejecting them.

### tool.output.constraint.tightened

**Default severity:** `NON_BREAKING`

A bound moved inward (`minLength`, `maximum`, `additionalProperties: false`, `uniqueItems`, `allOf` branch added, `anyOf` branch removed).

> [!NOTE]
> Input that was valid is now rejected. Loosen the bound, or stage the change.

### tool.output.default.changed

**Default severity:** `POTENTIALLY_BREAKING`

A `default` was added, removed or changed. The schema still validates; the behavior does not match.

> [!NOTE]
> The schema still validates, but calls that omit this argument now behave differently. Check telemetry for how often it is omitted before shipping.

### tool.output.deprecated.added

**Default severity:** `NON_BREAKING`

`deprecated: true` appeared on a property.

> [!NOTE]
> Check usage before removing it in a later release.

### tool.output.deprecated.removed

**Default severity:** `NON_BREAKING`

A property is no longer marked deprecated.

### tool.output.description.changed

**Default severity:** `DOCUMENTATION` or `POTENTIALLY_BREAKING`

A property `description` **or** `title` changed. Models read these when filling arguments.

> [!NOTE]
> Models read property descriptions when filling arguments. A changed one can change what gets passed.

### tool.output.enum.narrowed

**Default severity:** `NON_BREAKING`

Values removed from an `enum`.

> [!NOTE]
> Callers passing a removed value will now fail. Accept the old values and map them for one release.

### tool.output.enum.widened

**Default severity:** `BREAKING`

Values added to an `enum`.

> [!NOTE]
> Consumers switching exhaustively on this enum will not handle the new values.

### tool.output.header.changed

**Default severity:** `BREAKING`

`x-mcp-header` added, removed or changed: it alters how the call is transmitted over HTTP.

> [!NOTE]
> x-mcp-header changes how the call is transmitted over HTTP, so intermediaries routing on the mirrored header will stop matching.

### tool.output.property.added

**Default severity:** `NON_BREAKING`

A new optional property.

### tool.output.property.addedRequired

**Default severity:** `NON_BREAKING`

A new property that is immediately required.

> [!NOTE]
> Every existing call omits this property and will now fail validation. Add it as optional with a default, then require it a release later.

### tool.output.property.removed

**Default severity:** `BREAKING`

A property is gone.

> [!NOTE]
> Accept and ignore the property for one release so existing callers keep working, then remove it.

### tool.output.removed

**Default severity:** `BREAKING`

A declared `outputSchema` disappeared.

> [!NOTE]
> A client that generated types from this schema loses them. Restore the schema, or release the removal as a major version.

### tool.output.required.added

**Default severity:** `NON_BREAKING`

Optional → required.

> [!NOTE]
> Accept calls that omit it for at least one release, applying the previous default, then require it.

### tool.output.required.removed

**Default severity:** `BREAKING`

Required → optional.

> [!NOTE]
> Consumers may assume this field is always present in a result. Keep emitting it, or release the change as a major version.

### tool.output.schema.changed

**Default severity:** `BREAKING`

**The completeness net.** A difference the structured walk does not model. See §9.

> [!NOTE]
> This schema keyword is not modelled by the diff engine, so the change is reported as breaking until a human confirms otherwise.

### tool.output.type.changed

**Default severity:** `BREAKING`

Type sets are not comparable.

> [!NOTE]
> The type sets are not comparable, so no existing caller is guaranteed to still work.

### tool.output.type.narrowed

**Default severity:** `NON_BREAKING`

The `type` set shrank.

> [!NOTE]
> Keep accepting the removed types and coerce them for one release.

### tool.output.type.widened

**Default severity:** `BREAKING`

The `type` set grew.

> [!NOTE]
> Consumers typed against the narrower schema will not handle the new types.

## Tools

### tool.added

**Default severity:** `NON_BREAKING`

A new tool appears.

### tool.annotations.added

**Default severity:** `POTENTIALLY_BREAKING`

An annotation appeared. Agents use these to decide whether to call.

> [!NOTE]
> Confirm clients that filter tools by annotation still see this one.

### tool.annotations.changed

**Default severity:** `POTENTIALLY_BREAKING`

An annotation's value changed.

> [!NOTE]
> Confirm clients that filter or rank tools by annotation still behave as intended.

### tool.annotations.removed

**Default severity:** `POTENTIALLY_BREAKING`

An annotation disappeared.

> [!NOTE]
> A client filtering on this annotation will no longer match this tool.

### tool.annotations.safetyWeakened

**Default severity:** `POTENTIALLY_BREAKING`

`readOnlyHint`/`idempotentHint` left `true`, or `destructiveHint`/`openWorldHint` left `false`. The tool withdrew a promise. Escalate this rule to `BREAKING` in config if you gate on annotations.

> [!NOTE]
> The tool withdrew a behavioural promise. Clients that auto-approve read-only or idempotent tools will now prompt, or worse, will have already auto-approved a tool that is no longer read-only. Set severity_overrides.tool.annotations.safetyWeakened to BREAKING if you gate on annotations.

### tool.description.changed

**Default severity:** `DOCUMENTATION` or `POTENTIALLY_BREAKING`

`description` changed. This is the primary tool-selection signal.

> [!NOTE]
> The description is the primary tool-selection signal. Re-run your evaluations: a model may now pick this tool where it did not, or stop picking it where it did.

### tool.icons.changed

**Default severity:** `DOCUMENTATION`

`icons` changed.

### tool.meta.changed

**Default severity:** `NON_BREAKING`

`_meta` changed. Emitted for every `_meta` change; the MCP Apps keys are also interpreted by the `tool.ui.*` rules below (§7.1).

### tool.removed

**Default severity:** `BREAKING`

A tool is gone.

> [!NOTE]
> Keep the tool deprecated for at least one release. Review observed usage and unmeasured consumers before removal; no observed calls is not proof of no dependency.

### tool.renamed

**Default severity:** `BREAKING`

A removal and an addition share an identical schema fingerprint, one candidate each way. Reported as one change instead of two.

> [!NOTE]
> Keep the old name as an alias that forwards to the new one for at least one release. Agents have the old name in their context and in cached tool lists.

### tool.title.changed

**Default severity:** `DOCUMENTATION` or `POTENTIALLY_BREAKING`

`title` changed. Clients display it; models read it.

### tool.ui.resourceUri.added

**Default severity:** `NON_BREAKING`

The tool now links a `ui://` template, so hosts render its results with a UI.

### tool.ui.resourceUri.changed

**Default severity:** `POTENTIALLY_BREAKING`

The tool links a different template. Hosts may have prefetched and cached the old one.

> [!NOTE]
> Hosts may have prefetched and cached the old template. Keep serving the old URI for a release, and make sure the new template accepts the structuredContent this tool returns.

### tool.ui.resourceUri.removed

**Default severity:** `POTENTIALLY_BREAKING`

The tool no longer links a UI template. Calls succeed; hosts fall back to text and users lose the UI.

> [!NOTE]
> Hosts fall back to plain text, so calls still succeed, but users lose the UI they had. If this is intentional, say so in the release notes; otherwise restore `_meta.ui.resourceUri`.

### tool.ui.visibility.narrowed

**Default severity:** `BREAKING`

The tool lost the `"model"` audience (hosts drop it from the agent's tool list) or the `"app"` audience (hosts reject the UI's calls).

> [!NOTE]
> Without "model" the host takes the tool out of the agent's tool list, which is a removal for every agent; without "app" the host rejects calls from the UI. Keep the previous visibility for a release, or add a replacement first.

### tool.ui.visibility.widened

**Default severity:** `NON_BREAKING`

The tool gained the `"model"` or `"app"` audience.

## Resource templates

### resourceTemplate.added

**Default severity:** `NON_BREAKING`

A new `uriTemplate`.

### resourceTemplate.annotations.changed

**Default severity:** `POTENTIALLY_BREAKING`

—

### resourceTemplate.description.changed

**Default severity:** `DOCUMENTATION` or `POTENTIALLY_BREAKING`

—

### resourceTemplate.meta.changed

**Default severity:** `NON_BREAKING`

`_meta` changed.

### resourceTemplate.mimeType.changed

**Default severity:** `BREAKING`

—

> [!NOTE]
> Consumers parsing the body by its declared type will fail.

### resourceTemplate.name.changed

**Default severity:** `POTENTIALLY_BREAKING`

—

### resourceTemplate.removed

**Default severity:** `BREAKING`

A `uriTemplate` is gone.

> [!NOTE]
> Clients constructing URIs from this template will stop being able to.

### resourceTemplate.title.changed

**Default severity:** `DOCUMENTATION` or `POTENTIALLY_BREAKING`

—

## Resources

### resource.added

**Default severity:** `NON_BREAKING`

A new resource URI.

### resource.annotations.changed

**Default severity:** `POTENTIALLY_BREAKING`

`audience` / `priority` etc. changed.

> [!NOTE]
> Annotations like audience and priority steer which resources a client surfaces.

### resource.description.changed

**Default severity:** `DOCUMENTATION` or `POTENTIALLY_BREAKING`

`description` changed.

### resource.meta.changed

**Default severity:** `NON_BREAKING`

`_meta` changed. Emitted for every `_meta` change, alongside any `resource.ui.*` rule.

### resource.mimeType.changed

**Default severity:** `BREAKING`

A consumer parsing the body will fail.

> [!NOTE]
> Consumers parsing the body by its declared type will fail.

### resource.name.changed

**Default severity:** `POTENTIALLY_BREAKING`

Models select resources by name.

> [!NOTE]
> Models select resources by name; a rename changes what gets read.

### resource.removed

**Default severity:** `BREAKING`

A resource URI is gone.

> [!NOTE]
> Clients holding this URI will start getting errors. Keep it, or redirect it.

### resource.title.changed

**Default severity:** `DOCUMENTATION` or `POTENTIALLY_BREAKING`

`title` changed.

### resource.ui.csp.narrowed

**Default severity:** `BREAKING`

An origin left a UI template's CSP list, so the host blocks the template's requests to it.

> [!NOTE]
> The host builds the template's Content-Security-Policy from these lists, so requests to a removed origin are blocked. Remove the origin only after the template stops using it.

### resource.ui.csp.widened

**Default severity:** `NON_BREAKING`

An origin was added to a UI template's CSP list.

### resource.ui.domain.changed

**Default severity:** `POTENTIALLY_BREAKING`

The UI template's dedicated origin was set, unset or changed. Anything keyed on the origin must follow.

> [!NOTE]
> The template now runs on a different origin. Update anything keyed on the old one (OAuth redirect URIs, CORS and API-key allowlists) before releasing.

### resource.ui.permissions.added

**Default severity:** `NON_BREAKING`

The template requests a new sandbox permission.

### resource.ui.permissions.removed

**Default severity:** `POTENTIALLY_BREAKING`

The template no longer requests a sandbox permission (`camera`, `microphone`, `geolocation`, `clipboardWrite`).

> [!NOTE]
> The host stops granting this browser capability to the template. Confirm the template detects its absence instead of failing.

### resource.ui.widgetDescription.changed

**Default severity:** `DOCUMENTATION` or `POTENTIALLY_BREAKING`

`openai/widgetDescription` changed. ChatGPT puts it in the model's context when the template loads.

> [!NOTE]
> ChatGPT puts this summary in the model's context when the template loads. Re-run any evaluation that depends on how the model talks about the UI.

## Prompts

### prompt.added

**Default severity:** `NON_BREAKING`

A new prompt.

### prompt.argument.added

**Default severity:** `NON_BREAKING`

A new optional argument.

### prompt.argument.addedRequired

**Default severity:** `BREAKING`

A new required argument.

> [!NOTE]
> Every existing invocation omits it. Add it as optional first.

### prompt.argument.description.changed

**Default severity:** `DOCUMENTATION` or `POTENTIALLY_BREAKING`

—

### prompt.argument.nowOptional

**Default severity:** `NON_BREAKING`

Required → optional.

### prompt.argument.nowRequired

**Default severity:** `BREAKING`

Optional → required.

> [!NOTE]
> Accept invocations that omit it for at least one release.

### prompt.argument.removed

**Default severity:** `BREAKING`

An argument is gone.

> [!NOTE]
> Accept and ignore the argument for one release, then remove it.

### prompt.description.changed

**Default severity:** `DOCUMENTATION` or `POTENTIALLY_BREAKING`

—

### prompt.removed

**Default severity:** `BREAKING`

A prompt is gone.

> [!NOTE]
> Clients invoking this prompt by name will start getting errors.

### prompt.title.changed

**Default severity:** `DOCUMENTATION` or `POTENTIALLY_BREAKING`

—

## Severities

| Severity | Means | CI default |
| --- | --- | --- |
| `BREAKING` | A correct existing caller can stop working. | fail |
| `POTENTIALLY_BREAKING` | Behaviour or model-visible semantics changed. | warn |
| `NON_BREAKING` | Strictly additive or widening. | pass |
| `DOCUMENTATION` | Prose changed too little to plausibly move a model. | pass |

Severity is assigned by pure code. No model participates in it.
