DecisionRecordedReceipt Q4 decision — recorded fact vs proposal/vote lineage
Status: draft — design / audit decision (not runtime implementation)
Truth class: descriptive
Canonical: no — current implementation truth lives in docs/STATE.md and docs/PHASE_PROGRESS.md
Last Reviewed: 2026-07-02
Source basis: read against main @ 2b2622ca. Code anchors were verified at that commit — re-verify before relying on exact numbers.
Related: issues #1748 (Institutional Process Substrate milestone) · #2141 (vertical institutional spine control) · PR #2280 (merged DecisionRecordedReceipt design/audit contract, docs/design/decision-recorded-receipt.md) · PR #2278 (Q3 taxonomy decision, docs/design/deliberation-entry-kind-taxonomy.md — the sibling decision-doc pattern) · ADR-0026 (receipt envelope, Layer 2) · ADR-0014 (decision-receipt provenance) · ops/ideas/framing/institutional-process-substrate.md (idea-0019 framing brief; open question Q4) · docs/spec/effect-dispatch-contract.md (effect dispatch keyed on the proposal/vote lineage)
Narrow decision document closing framing-brief open question Q4 for the
DecisionRecordedReceiptslice only. The merged #2280 contract pinned the Q4-independent skeleton and blocked implementation on four Q4 branches: (a) decision representation, (b) reference posture toward the proposal/voteGovernanceDecisionReceiptlineage, (c) deciding-body handle, (d) the fate of the deferredresolutiondeliberation kind. This document decides all four. It decides nothing else: no runtime change, no new receipt fields, no proposal/vote migration. Receipts record institutional facts. They grant zero authority.
1. Problem
PR #2280 defined the fourth ProcessTransitionReceipt class,
DecisionRecordedReceipt (proposed tag icn:gov:decision_recorded:v1),
and deliberately refused to pin its runtime :v1 layout until Q4 is
decided. The framing brief's Q4, verbatim:
How does
HumanDecisionSetrelate to the existing proposal/vote machinery? Is the existing path one specialization ofHumanDecisionSet, or a parallel surface that the spine names but does not absorb?
The question is live because ICN already has a decision receipt: the
proposal/vote GovernanceDecisionReceipt lineage under
icn:gov:decision:v1/v2/v3. If the process-spine class silently absorbed,
referenced, or duplicated that lineage, it would either fork a load-bearing
audit chain or become proposal/vote outcome machinery by accident — the
exact failure the #2280 audit warns against. And the decision must land
before implementation: every unresolved branch changes the :v1 canonical
hash layout or the class's lineage relationships, and the landed rule (from
the #2278 review cycle) is that hash-participating structure is decided in
writing before a tag is pinned, never silently in an implementation PR.
2. Prior-art audit (verified at 2b2622ca)
The proposal/vote decision lineage — outcome machinery, load-bearing.
icn/crates/icn-governance/src/proof.rs: GovernanceDecisionReceipt
(~L226, tag icn:gov:decision:v1 ~L251) carries proposal_id,
domain_id, outcome (Accepted / Rejected / NoQuorum), vote_tally,
vote_hash, and the canonical decision_hash;
GovernanceDecisionReceiptV2 (~L541, :v2) adds
capability_scope_presented and the frozen mandate-attestation taxonomy;
GovernanceDecisionReceiptV3 (~L820, :v3) adds the ProcessAuthorized
attestation mode; GovernanceDecisionAttestation (~L1037,
icn:gov:attest:v1) is the node-local witness. Downstream, this lineage is
structural: decision_hash is the load-bearing identifier of the effect
dispatch chain (docs/spec/effect-dispatch-contract.md: decision →
InstitutionalEffectRecord → EffectManifest → subsystem dispatch); the
gateway ReceiptStore keeps secondary indexes of mandates and authority
grants by decision_hash (icn/crates/icn-gateway/src/receipt_store.rs
~L80–84) plus lookups by proposal_id and domain_id; action cards
(contract: ADR-0027; the
surface ADR-0020 promised, with the end-to-end proposal/vote proof-loop
verification recorded at ADR-0020 step 7) close the proposal/vote proof
loop against it; ADR-0014 records its
authority posture ("authoritative for 'the decision happened,' but it does
not itself bind authority-to-execute"). This is outcome/tally/proposal
lineage — a specific decision rule (vote over a proposal) with its
consequences wired in. It is not, and was never designed as, the generic
recorded-decision fact of the process spine.
The process-transition receipt lineage — recorded facts, landed.
Three classes, all wired end to end through the opaque cascade:
ProcessGateResultReceipt (icn:gov:process_gate_result:v1, #2144/#1755),
ProcessSessionOpenedReceipt (icn:gov:process_session_opened:v1,
#2275/#2276), DeliberationEntryRecordedReceipt
(icn:gov:deliberation_entry_recorded:v1, #2277/#2278/#2279). All are
body-blind or content-fingerprinting, session-or-domain-anchored,
idempotent-on-stable-identity, fail-closed on conflict, and grant zero
authority. The #2278 taxonomy decision already operated the Q4 firewall
inside this lineage: no approve/vote/outcome kind may enter
DeliberationEntryKind by append — "an outcome-bearing kind is a semantic
boundary change requiring its own design decision (and almost certainly a
different receipt class: DecisionRecord / HumanDecisionSet territory)"
— and resolution was deferred with discriminant 10 reserved.
The framing brief's own definitions. HumanDecisionSet is "the
structured set of decision moments inside one ProcessSession: who
decided, in what role, by what rule (vote threshold, consensus, mandate
from a parent body, delegated authority, emergency authority, etc.), with
what tally or attestation, and over which proposed outcome" — and the
brief's dogfood sketch positions it explicitly as "a read-model that
names who decided by what rule with what tally or attestation."
DecisionRecord is "the persisted, signed artifact that names the chosen
outcome and binds it to the deliberation that produced it." The brief also
separates deciding from doing: "a decision is not a mutation. A
decision authorizes a mutation" — with ActivationRequest as the explicit
boundary crossing.
No DecisionRecordedReceipt runtime exists. The strings
DecisionRecordedReceipt and decision_recorded appear nowhere under
icn/ at 2b2622ca. The only definitions are the merged #2280 contract
and status/backlog references.
3. The four Q4 axes — options and decision
Axis A — representation of the recorded decision in :v1
Options considered:
- Opaque recorded-decision fact —
body_hashfingerprint only, no typed outcome/kind field. CHOSEN. - Typed
DecisionRecordin the receipt — outcome enum / chosen-outcome naming inside the receipt payload. Rejected: the framing brief'sDecisionRecord"names the chosen outcome"; putting outcome naming in the receipt makes the receipt the outcome artifact, which is exactly the semantic boundary #2278 §7 placed outside the process-input lineage, and it drags outcome-taxonomy design (accepted? adopted? consensus-reached? deferred?) into a hash layout before any consumer exists. - Typed
HumanDecisionSetin the receipt — who/role/rule/tally structure. Rejected: the brief itself positionsHumanDecisionSetas a read-model, not a receipt payload; embedding it would freeze who-decided-by-what-rule semantics (idea-0020AuthorityBasisterritory) into a v1 hash before that design exists. - Hybrid (opaque body + minimal typed outcome flag). Rejected: inherits the objections to 2 at reduced fidelity — a one-bit outcome is still outcome machinery, still hash-participating, still undesigned.
Decision A: :v1 records an opaque recorded-decision fact. The
receipt witnesses that a decision artifact was recorded — attributed
(recorded_by), timestamped (recorded_at), content-fingerprinted
(body_hash) — and nothing about what the decision says. The
outcome-naming content lives in the (never-stored, fingerprinted) decision
body; structured who/rule/tally legibility arrives later as a read-model
or a future tag version, not in this hash layout.
Axis B — relationship to GovernanceDecisionReceipt
Options considered:
- Absorb — make the proposal/vote lineage a specialization of the
process-spine class. Rejected:
icn:gov:decision:v1/v2/v3is load-bearing (effect dispatch keying, mandate and authority-grant indexes bydecision_hash, action-card proof loops, 20+ documented callers); absorbing means retagging or adapter-wrapping live audit chains for zero consumer benefit. - Reference — an optional field carrying the lineage's
decision_hashwhen a session's decision came from a proposal/vote. Rejected for:v1: an optional hash-participating field is still a layout commitment, and it pre-answers the posture question inside a receipt slice instead of an ADR. A session whose decision was produced by a proposal/vote can already be evidenced without a receipt field: the decision body (fingerprinted bybody_hash) can name theproposal_id/decision_hash, and read-models can join the two lineages at the app layer. - Parallel with explicit non-convergence. CHOSEN.
- Conversion/adapters now. Rejected as premature: no consumer exists; adapters without consumers are speculative surface.
Decision B: the answer to the framing brief's question is "a parallel
surface that the spine names but does not absorb." The proposal/vote
path stays exactly what it is — one concrete, heavily-wired decision rule
with its own receipt lineage. DecisionRecordedReceipt records the
generic institutional fact that a process session's decision was recorded,
whatever rule produced it. The two lineages never converge tags, never
share fields, never share stores. Any future formal reference or adapter
between them is a :v2-or-later change (or a separate adapter class)
requiring its own explicit ADR — never a silent addition to :v1.
Axis C — deciding-body handle in :v1
Options considered:
- No deciding-body field in v1. CHOSEN.
- Opaque
deciding_body_refstring. Rejected: even an opaque ref bakes "there is a single nameable deciding body" into the hash layout — which is false for consensus processes, delegated chains, and emergency authority — and it reads as an authority claim the receipt explicitly does not make. - Typed body/member/quorum structure. Rejected: this is
HumanDecisionSetby another name (Axis A, option 3). - Defer to future
HumanDecisionSetwork. This is the same choice as 1, stated forward: when idea-0020/HumanDecisionSetdesign lands, it composes with this receipt as a read-model or future tag version.
Decision C: recorded_by remains the only actor field in :v1, and it
remains recorder evidence — not decider, not author, not approver.
Who decided, in what role, by what rule is deferred to the
HumanDecisionSet read-model / idea-0020 lane, exactly where the framing
brief puts it.
Axis D — fate of the deferred resolution deliberation kind
Options considered:
- Keep deferred (discriminant
10stays reserved). CHOSEN. - Add
resolutiontoDeliberationEntryKindv1 now. Rejected: #2278 deferred it precisely because it straddles the input/outcome boundary; nothing about this decision sharpens the input reading, and v1 kind appends require their own ADR/addendum anyway. - Move it to decision territory as a typed decision kind. Rejected:
Axis A chose no typed decision kinds in
:v1; and withDecisionRecordedReceiptexisting, "the resolution of the matter" is naturally the content of a recorded decision body — no new kind needed to express it. - App-layer mapping only. Already legal and unaffected: the #2278
vocabulary firewall lets charters map institutional vocabulary (e.g.
"proposed resolution offered into deliberation") onto existing input
kinds such as
amendmentorrecord_onlyat the app layer, with no core change. This decision reaffirms that path and adds nothing to core.
Decision D: resolution stays deferred and MUST NOT be added to
DeliberationEntryKind v1. The outcome reading of "resolution" now has
a home (the recorded decision's fingerprinted body); the input reading
("resolution offered") remains expressible via app-layer mapping. A sharp
input-only resolution kind may still be appended later via the #2278
evolution rule if a real consumer demonstrates the need — this document
neither performs nor forecloses that append.
4. Decision summary
Option A — DecisionRecordedReceipt :v1 is a generic recorded-decision
fact, parallel to and explicitly non-convergent with
GovernanceDecisionReceipt.
Binding consequences:
:v1stays body-hash-only. No vote, proposal, tally, outcome, quorum, or effect-dispatch field — ever, in this tag version.:v1usesrecorded_by(recorder evidence), neverdecider,author, orapprover.:v1carries no deciding-body handle.:v1carries exactly the merged #2280 §4 field set —domain_id,session_id, caller-opaquedecision_id,recorded_by,recorded_at,body_hash,record_hash— and nothing else.- Stable duplicate identity is narrower than the field set, exactly as
#2280 §4 pins it: same
(domain_id, session_id, decision_id)+ samerecorded_by+ samebody_hash→ idempotent retry returning the ORIGINAL receipt.recorded_atand the derivedrecord_hashare not identity inputs — a retry never fails, restamps, or conflicts merely because time moved; a mismatch onrecorded_byorbody_hashis a fail-closeddecision_recorded_conflict409. - The relationship to
GovernanceDecisionReceiptstays out of the v1 hash layout entirely.icn:gov:decision_recorded:v1andicn:gov:decision:v1/v2/v3never converge, never share fields, never share typed stores. - Any future reference to the proposal/vote lineage, deciding-body
handle, or typed outcome is a
:v2-or-later tag version or a separate adapter class, after its own explicit ADR — and per #2280's contract-sync instruction, any such hash-participating field joins stable duplicate identity (mismatch = fail-closed 409, never a silent idempotent return). resolutionremains deferred out ofDeliberationEntryKindv1; discriminant10stays reserved.
5. Hash-layout consequence
No change to #2280. The merged contract is implementation-ready as
written. This decision adds zero fields, removes zero fields, and
changes zero encodings: the :v1 canonical layout is exactly #2280 §4
(domain tag first; string fields length-prefixed u64 LE; recorded_at LE;
body_hash raw fixed-32 with no length prefix; equality anchored to
record_hash). #2280 does not need revision, amendment, or a
contract-sync edit — its "deliberately absent" list is hereby confirmed
absent for :v1, and its §4 contract-sync instruction (Q4-added fields
join duplicate identity) now applies to any future tag version rather
than to :v1. There are no silent layout changes available to the
implementation PR: it implements #2280 §4–§8 byte-for-byte or it stops and
comes back to design.
6. Boundaries (what this receipt is and is not)
DecisionRecordedReceiptrecords that a decision fact was recorded against an opened process session. That is all.- It does not prove the decision was valid, binding, voted, approved,
quorum-backed, authorized, legitimate, or effect-dispatched. Bindingness
and authority are future charter/policy/
HumanDecisionSet/idea-0020 work; the deciding→doing boundary stays with the framing brief'sActivationRequestconcept and the futureActivationCrossedReceiptclass, neither of which this document touches. - The proposal/vote lineage —
GovernanceDecisionReceiptv1/v2/v3, attestations, effect dispatch, mandate/authority-grant indexes, action cards — remains intact, separate, and untouched. - Receipts record institutional facts. They grant zero authority.
7. Implementation instruction
With Q4 decided as above, the implementation blocker recorded in #2280
§10/§11 is cleared. The next PR in this lane may implement
DecisionRecordedReceipt exactly from the merged #2280 contract
(§4–§8) plus this document — one focused PR, mirroring how #2279
implemented #2277 + #2278. Required tests beyond #2280's §8 matrix
(restated here as binding):
- Family-tag separation from
icn:gov:decision:v1,:v2, and:v3(identical field bytes, different hashes), with a comment stating the lineages must never converge. - Payload audit: no proposal, vote, tally, outcome, quorum, mandate, or effect-dispatch field anywhere in the persisted payload.
recorded_bysemantics: recorder evidence only; participates in stable duplicate identity; distinct recorders on the samedecision_idare a fail-closed conflict.body_hashonly: raw body never persisted; fixed-32, no length prefix, per the landed convention.- Duplicate/idempotency/conflict behavior per #2280 §4 (original-return
on stable-identity retry;
decision_recorded_conflict409 otherwise). - Session-open precondition (
decision_recorded_session_not_opened, 404; no silent session creation). - No
resolutionkind creep:DeliberationEntryKindremains exactly the #2278 ten-kind list; discriminant10remains unassigned. - Existing
GovernanceDecisionReceiptv1/v2/v3 behavior byte-identical (typed store, effect dispatch, action-card suites untouched and green). - Existing process receipts unchanged (session-open, gate-result, deliberation-entry suites green, byte-identical semantics).
8. Explicit non-goals
No runtime implementation in this PR. No DecisionRecordedReceipt code,
route, proof type, backend method, manager method, or generated-inventory
change. No HumanDecisionSet runtime or read-model implementation. No
proposal/vote migration, retagging, or adapter. No effect-dispatch
changes. No action-card triggers. No activation-crossed / mutation-plan /
mutation-applied / evidence-packet classes. No served-OpenAPI or SDK
publication. No privacy/redaction evidence export; no accessibility-gate
run. No #1748 closure; no #2141 closure; no #2081/#2080/#2274 work. No
process-runtime, Phase-2, production, pilot, member/organizer-readiness,
live-federation, or service-hosting claims.
9. Validation (this document's PR)
Docs-only change set: this file, a docs/registry.toml row, a
docs/INDEX.md link, and the regenerated docs/DOCUMENT_REGISTRY.md
(regeneration after registry row additions is required by that file's
header). Validation: git diff --check, python3 docs/scripts/doc_control_check.py --repo . --registry docs/registry.toml
(no new warnings), python3 scripts/check-state-lag.py. No route,
OpenAPI, or generated-inventory files are touched, so none are
regenerated.