Part V · Contracts · Plate 08

Concern lifecycle · ledger

On this page

6. Soma Concern Lifecycle, Fire Ledger and Tolerance (S7, 2026-10-31)

Standalone: Soma alone gains concern history, specificity (tolerance) and author ≠ certifier with no other organ present. Composition: the census reads the S4 verdict log (5.5) when it exists; cns curate runs recall and tolerance.

6.1 Concern front matter (writer: the concern author and soma concerns init/promote; reader: every soma concerns command)

6.2 soma concerns check: author is not certifier

A concern gates only in the form certified at the merge base of the evaluated changeset, and only when that form is active. The base's concern files are read from the base commit itself, through the base's own soma.toml docs_dir, so a changeset that moves the concerns directory cannot hide them.

Markdown adds, after fired: <n>, not gating: <id> (<state>), ... or not gating: none; JSON adds per fired entry state, stateReason, version (current | base), gating, and a top-level lifecycle object. fired: <n> counts distinct fired concern ids, gating or not; the rubric is vacuous when no gating concern fired.

6.3 Tolerance set (writer: the consumer; reader: soma concerns tolerance, promote, cns curate)

<docs_dir>/concerns/tolerance.yaml, the "self" counterpart of recall.yaml: commits known to be good (they passed the consumer's sealed tests), each naming concerns that must stay silent on it.

schemaVersion: 1
entries:
  - commit: '<sha>'            # quoted; a root commit cannot be evaluated (no parent) and is refused
    expect_silent: [concern-a, concern-b]
    note: why it is known to be good

Unknown keys are refused by name (exit 2); a named concern that is not a valid concern is refused (exit 2). An optional structural delta sits at <docs_dir>/concerns/tolerance/<commit>.delta.json, as for recall. soma concerns tolerance [--only <id>] evaluates every entry against its first parent and fails (exit 1) when a concern fires on more of the commits naming it than its tolerance: rate allows (strictly greater); a concern no entry names is not evaluated (with --only: exit 3). No tolerance.yaml: tolerance: not evaluated (no <path>), exit 3. soma concerns recall without a recall.yaml likewise prints recall: not evaluated (no recall.yaml) and exits 3 (it was exit 2 before S7).

6.4 Concern ledger (writer: soma concerns census; readers: soma concerns ledger [--verify], S9)

<generated_dir>/concern-ledger.jsonl (default .soma/concern-ledger.jsonl, git-excluded). Each soma concerns census --last <n> [--ref <rev>] appends one row per valid concern, schema soma.concern-ledger.v1: {schema, ts, concern_id, rev_range: {ref, head, last, commits, hash}, concern_sha256, state, severity, fired, fired_expected, fired_unexpected, never_fired, rubric_pass, rubric_fail, not_evaluated, overrides, fires: [{sha, delta_sha, expected, disposition, outcome}], inputs: {recall_sha256, verdicts: {lines, sha256} | null}, prev, row_sha256}.

6.5 cns curate (reader of 6.3 and of recall.yaml)

In a Soma-initialised repository cns curate runs soma concerns recall and then soma concerns tolerance, after soma verify and before the Engram layers. Both always run. Exit 0 is a pass. Exit 3 (no recall.yaml or no tolerance.yaml) is printed as Soma: concerns <recall|tolerance> not evaluated (exit 3) ... and does not fail curate. Any other exit fails curate with ERROR: 'soma concerns <recall|tolerance>' failed (exit <n>): 1 (a recall miss, or a concern above its tolerance), 2 (a refusal, such as a malformed set) or a missing binary. This needs a soma with S7; an older soma has no concerns tolerance (exit 2), so curate fails and names it.