# description
Manifest shape for an `Action` extension. An action operates on one or more nodes in one of two modes: `deterministic` (code runs in-process, returns a report JSON directly) or `probabilistic` (kernel renders a prompt, a runner executes it against an LLM, the callback closes the job). The `mode` discriminator drives which additional fields are required. See `architecture.md` §Execution modes for the cross-extension contract.

# properties.mode.description
`deterministic`: the plugin's code computes the report synchronously, no job file, no runner. `probabilistic`: the kernel renders a prompt + preamble into a job file; a runner executes it via `RunnerPort`; `sm record` closes the job.

# properties.reportSchemaRef.description
Absolute or relative reference to the JSON Schema the report MUST validate against. MUST extend `report-base.schema.json` (directly or transitively). Validation failure → job transitions to `failed` with reason `report-invalid`.

# properties.expectedDurationSeconds.description
Best-effort estimate of wall-clock duration. Drives TTL (`ttl = max(expectedDurationSeconds × graceMultiplier, minimumTtlSeconds)`). Required for `probabilistic`; advisory for `deterministic`.

# properties.promptTemplateRef.description
Path (relative to the extension file) to the prompt template the kernel renders at `sm job submit`. REQUIRED when `mode: probabilistic`; FORBIDDEN when `mode: deterministic`. The template MUST NOT interpolate user text outside `<user-content>` blocks (see `prompt-preamble.md`).

# properties.precondition.description
Declarative filter that nodes must satisfy for this action to be applicable. Consumed by `--all` fan-out, UI button gating, `sm actions show`.

# properties.precondition.properties.kind.description
Node kinds this action accepts. Open-by-design (matches `node.schema.json#/properties/kind`): an action declared with `kind: ['cursorRule']` is valid as long as some Provider classifies into `cursorRule`. Omitted → any kind.

# properties.precondition.properties.provider.description
Provider ids whose nodes this action accepts. Omitted → any Provider.

# properties.precondition.properties.custom.description
Free-form precondition strings the kernel forwards to the action for runtime evaluation. Example: `frontmatter.metadata.source != null`.

# properties.expectedTools.description
Hint to a Skill agent / CLI runner about what tools the rendered prompt expects access to (`Bash`, `Read`, `WebSearch`, …). Host MAY filter or warn. No normative enforcement in v0.

# properties.fanOutPolicy.description
`per-node` (default): `sm job submit --all` produces one job per matching node. `batch`: produces one job whose prompt template receives the full list. Batch actions tend to hit context limits; use sparingly.