# description
Base manifest shape common to every extension kind. Kind-specific schemas (`provider`, `extractor`, `rule`, `action`, `formatter`, `hook`) extend this via `allOf` and add a discriminant `kind` literal plus kind-specific fields. camelCase keys throughout. Closed-content enforcement (unknown keys = bug) lives on the kind schemas via `unevaluatedProperties: false`; those see base's evaluated keys through the `allOf` composition. Adding closure here too would force every kind schema to re-list every base key, which is the footgun the spec used to trip on before 2026-04-22.

# properties.id.description
Kebab-case identifier unique within the extension's kind across the same plugin. The kernel registers every extension under the **qualified** id `<plugin-id>/<id>` (e.g. `core/frontmatter`, `claude/slash`, `hello-world/greet`) — see `architecture.md` §Extension kinds and `plugin-author-guide.md` §Qualified extension ids. Authors declare only the short id here; the qualifier is composed by the loader from the manifest's `id` (or, for built-ins, from the bundle declaration in `built-ins.ts`). The pattern is intentionally constrained to a single kebab-case segment without the `/` separator: the qualifier always lives in the plugin id, never in the extension id.

# properties.kind.description
Discriminant. MUST match the file exporting this manifest; kind mismatch → load-error.

# properties.version.description
Extension semver. Bumped independently from the plugin version; frozen into `state_executions.extension_version` on every run for reproducibility.

# properties.description.description
One-to-three sentences explaining what the extension does. Rendered by `sm <kind>s list`.

# properties.stability.description
Maturity tag. The kernel MAY warn when an `experimental` extension is used in CI (`--strict`).

# properties.preconditions.description
Free-form predicates the kernel evaluates before offering this extension. Canonical keys: `kind=<node-kind>`, `provider=<provider-id>`, `frontmatter.<path>=<value>`. Unknown keys are skipped with a warning, not rejected.

# properties.entry.description
Optional path to the module exporting this extension (relative to the plugin root). Absent → the kernel uses the path listed in the plugin manifest's `extensions[]` array.