dev.idiolect.deliberationOutcome

Observer-aggregated tally for a deliberation. Not a participant-authored record: produced by an observer fold over the vote stream and published from the observer's repo. Consumers reading a closed deliberation can fetch the outcome directly rather than re-folding every vote. Tallies are per-statement and per-stance, so consumers can render a Polis-style opinion map without further computation.

Source: lexicons/dev/idiolect/deliberationOutcome.json · Rust: idiolect_records::DeliberationOutcome · TS: @idiolect-dev/schema/deliberationOutcome · Fixture: idiolect_records::examples::deliberation_outcome

Shape

FieldTypeRequiredNotes
deliberationstrongRecordRefyesAT-URI + CID for the deliberation.
statementTalliesarray (≤4096) of statementTallyyesPer-statement vote counts.
adoptedarray (≤256) of strongRecordRefnoStatements the community adopted.
stanceVocabvocabRefnoVocab the per-tally stance slugs resolve against.
computedAtdatetimeyesWhen the observer computed this tally.
tooltoolnoIdentity and version of the aggregator.
occurredAtdatetimeyesPublication timestamp.

statementTally

SubfieldTypeRequiredNotes
statementstrongRecordRefyesThe statement these counts aggregate.
countsarray (≤64) of stanceCountyesPer-stance vote counts.
weightedCountsarray (≤64) of stanceCountnoPer-stance weighted vote counts (when votes carried weight). Scaled by 1000.

stanceCount

SubfieldTypeRequiredNotes
stancestring (≤256)yesStance slug, resolved through the outcome's stanceVocab.
countnon-negative integeryesVote count. For weightedCounts, scaled by 1000.

Field details

Why outcomes are observer-published

The deliberation owns the topic; participants own the statements and votes. The aggregate is opinion: it depends on the observer's fold method, the cut-off time, and which encounter kinds it weights. Two observers can produce different but defensible outcomes for the same deliberation.

The substrate's answer: outcomes are records, signed by the observer, comparable across observers. A consumer that distrusts one observer's fold can:

  • Fetch all outcomes for the deliberation.
  • Pick one based on the observer's identity or the tool field.
  • Require quorum among trusted observers.
  • Re-fold the vote stream itself.

Why a single stanceVocab per outcome

The outcome record uses one stance vocabulary across all tallies. An observer that sees votes referencing different vocabularies must either:

  • Publish separate outcomes per vocab, each tallying votes that share a vocab.
  • First translate via a mapEnum lens (see Open enums) into a single target vocabulary, then tally.

Mixing vocabularies in a single outcome is invalid: the same slug in two different vocabularies has different semantics, and adding their counts is meaningless.

statementTallies

One entry per statement that received at least one vote. Statements with zero votes are omitted. Each tally carries:

  • The statement (strong-ref, so consumers fetching the tally can fetch the exact statement revision being tallied).
  • The per-stance counts.
  • Optional weighted counts when the underlying votes carried weight.

The 4096-entry cap matches the maximum statement count per deliberation in practice; communities expecting more should publish multiple outcome records partitioned by statement window.

adopted

A list of strong-refs to statements the community adopted as the deliberation's resolution. An adopted statement is one the community treats as the answer to a question, the resolution of a proposal, or the action item from a grievance.

Adoption is a community decision, not a fold rule. The observer publishing the outcome typically follows the deliberation's publishing community: their criterion for adoption (majority agree, supermajority, consensus) is what the observer encodes in this list. A different observer running a different criterion would publish a different outcome.

adopted is empty when the deliberation closed without adoption (rejected, tabled, or closed without resolution).

tool and method versioning

The tool field carries the aggregator's identity and version. Two outcomes for the same deliberation produced by different tools (or different versions of the same tool) are not directly comparable: the algorithm differs. Consumers compare outcomes across tools at their own risk; the substrate records the tool identity so the comparison is at least informed.

Example

{
  "$type": "dev.idiolect.deliberationOutcome",
  "deliberation": {
    "uri": "at://did:plc:community/dev.idiolect.deliberation/3l5",
    "cid": "bafy..."
  },
  "statementTallies": [
    {
      "statement": {
        "uri": "at://did:plc:community/dev.idiolect.deliberationStatement/stmt1",
        "cid": "bafy..."
      },
      "counts": [
        { "stance": "agree",    "count": 42 },
        { "stance": "pass",     "count": 7  },
        { "stance": "disagree", "count": 3  }
      ]
    },
    {
      "statement": {
        "uri": "at://did:plc:community/dev.idiolect.deliberationStatement/stmt2",
        "cid": "bafy..."
      },
      "counts": [
        { "stance": "agree",    "count": 18 },
        { "stance": "pass",     "count": 12 },
        { "stance": "disagree", "count": 22 }
      ]
    }
  ],
  "adopted": [
    {
      "uri": "at://did:plc:community/dev.idiolect.deliberationStatement/stmt1",
      "cid": "bafy..."
    }
  ],
  "computedAt": "2026-04-30T00:00:00.000Z",
  "tool": {
    "name": "deliberation-tally",
    "version": "1.0.0"
  },
  "occurredAt": "2026-04-30T00:01:00.000Z"
}

Concept references