# description
A single row in the execution history (`state_executions`). One record per extension execution (Action or finder Analyzer), whether an external agent processed the job (agent) or the extension ran in-process.

# properties.kind.description
Which extension kind was executed. Single-valued in v1: every recorded execution is stamped `action`, including the run of a probabilistic finder Analyzer processed through the queue (the queue records the EXECUTION channel, not the extension kind; `state_jobs.extension_kind` is where the kind travels). Matches the `state_executions.kind` CHECK constraint in `db-schema.md`. The audit kind was removed pre-1.0; widening this enum later is an additive change.

# properties.extensionId.description
Id of the extension that ran (e.g. `ai-summarizer-action`).

# properties.extensionVersion.description
Semver of the extension implementation at execution time.

# properties.nodeIds.description
Target `node.path` values. Empty for whole-graph actions.

# properties.contentHash.description
Duplicate-prevention hash used at submit time: sha256 over the NUL-joined (0x00) tuple (extensionId, extensionVersion, node.path, bodyHash, frontmatterHash, promptTemplateHash). May be null for in-process actions that don't memoize.

# properties.status.description
Terminal status. History never stores `queued` or `running`, those live in `state_jobs` until they reach a terminal state.

# properties.failureReason.description
Normalized reason when `status = failed`. Null for `completed` and `cancelled` (both self-explanatory), mirroring `Job.failureReason`. `user-failed` records an operator-forced failure (`sm jobs fail`); a `cancelled` status is the operator's `sm jobs cancel` and carries no reason. `job-file-missing` mirrors the same enum value on `Job.failureReason` (legacy name preserved across the disk-to-DB shift).

# properties.exitCode.description
Exit code the recording agent reported for its execution, when it reports one. Null for in-process executions or when the agent reports none.

# properties.runner.description
Which execution path produced this record: an external agent via claim/record, or in-process deterministic code. Null when the action runs synchronously without dispatching.

# properties.durationMs.description
Finished - started. Stored denormalized for query speed.

# properties.tokensIn.description
Input tokens reported by the recording agent. Null if not applicable or not reported.

# properties.model.description
Executing model's name as SELF-REPORTED by the recording agent (`sm record --model <name>`). Unverifiable by design, like the token counts. Null when the agent does not declare one, and for in-process deterministic executions. Denormalized onto `state_findings.model` / `state_summaries.model` at record time.

# properties.reportPath.description
Legacy field preserved across the disk-to-DB shift. Under B2 (DB-only job artifacts) this is always null because reports live inline in `state_executions.report_json`. Phase A of Step 10 will rename to `report` (object/null) carrying the parsed payload; until then the field remains as documented for backward compat.

# properties.jobId.description
Originating job id when applicable. Null for in-process actions.