- Sashité for Developers
- Nostr
- NIPs
- Conclusion
NIP-XX
Conclusion
draft optional
This NIP defines a Nostr event kind by which a player of a chess-family session concludes it: a verdict that terminates the session, signed by one of its two players and binding by correctness — it is valid if and only if it states the outcome that the session’s rule system yields for the session’s public events at the moment of its publication, which any consumer holding the rule-system document can recompute.
Abstract
Defines kind: 3425, a regular event by which either of the two players of a chess-family session publishes its verdict. The event references the Game Session (kind 3422), assigns a numeric result to each player via tags, and identifies the termination cause via the content field. Its own canonical timing is the cutoff at which the session’s natural state is evaluated.
A conforming Conclusion terminates the session. No further events can alter the outcome.
Until the suite’s 2026-09-04 revision this kind was the Adjudication, signed by a designated arbiter in response to an Adjudication Request (kind 3424, retired). The two events are merged here, and the arbiter is gone: the cutoff is the Conclusion’s own timing, and the verdict is verified rather than believed.
Motivation
Every rule question a chess-family session raises — which candidate Ply of a slot is legal, what the position then is, whether it is terminal, how the clocks are charged, what the outcome is at a given instant — is a function of the session’s public events and of the rule-system document the session was founded on (kind 3420 §Match-terms tags, the rules term). Two conforming implementations of that document reach the same answer. A verdict therefore needs no authority to be correct; what it needs is a signed, public, timed event that fixes the instant at which the session is evaluated and anchors its outcome for consumers that do not recompute it on every read: rematches (kind 3420 §Rematch challenge), rating authorities (kinds 3426/3427), indexers. The Conclusion is that event:
- it closes the session at its own canonical timing (the cutoff);
- it distributes a quantified outcome between the two players (
100 / 0,0 / 100, or50 / 50); - it names the termination cause via a status string from the rule system’s vocabulary.
The Conclusion is signed by a player, not by a third party, and it asserts nothing the player is free to choose: the outcome it carries MUST be the one the rule system yields at its cutoff, and a Conclusion carrying any other outcome is structurally invalid — it does not terminate the session, exactly as a Ply that fails legality does not move a piece. A player who concludes while no objective cause stands — no termination on the board, no expired opponent clock, no draw offer to accept — does not thereby get a favourable verdict; they get the rule system’s residual reading of an invocation with no cause, which for the reference rule system is their own resignation (Statuses — Sanki §Implicit resignation). The Conclusion is thus also the suite’s resignation and draw-acceptance mechanism, without dedicated event kinds.
The numeric result is carried as tags because it is structured, per-player data that consumers extract without parsing the content. Note that relays index only single-letter tag names for filtering (NIP-01), so result tags are read client-side after fetching (by #e/#p), not used as relay-side filters. The termination status, by contrast, is a single opaque token and is therefore carried as the content payload rather than as a tag.
This NIP fixes the format and the protocol-level guarantees of the verdict (correctness as a conformance condition, idempotence, finality). It does not define rule-system-specific evaluation logic or a fixed vocabulary of termination statuses; those remain the responsibility of the rule-system document the session names and of its supporting documents. Whatever the vocabulary, it MUST be decidable from published events alone: a verdict is a function of the natural state and the session’s public events, never of unpublished claims.
Specification
Event kind
kind: 3425
Conclusion events are regular events per NIP-01: immutable once signed and broadcast.
Signing party
The event MUST be signed by one of the two players of the session — the player-marked pubkeys of the referenced Game Session (kind 3422 §Players). Either player may conclude, at any moment after t₀, whether or not it is their turn to move. A Conclusion signed by any other pubkey is invalid and MUST be ignored.
Attestation by the designated timestamper (attested mode)
This section applies in attested mode. In self-timed mode the Conclusion’s canonical timing is its own created_at, established by acceptance at one of the session’s designated timing relays (Canonical Timing §Canonical timing of an event).
The designated timestamper publishes an Event Timestamp Attestation (kind 3410) referencing this Conclusion via the required attests-marked e tag. Its created_at is then the Conclusion’s canonical timing — the cutoff, and the timing for race resolution.
The structure of the Conclusion Attestation is:
["e", "<conclusion_event_id>", "<relay_hint>", "attests"]
["e", "<game_session_event_id>", "<relay_hint>", "<app>:session"]
The second e tag carries an application-namespaced discovery marker <app>:session referencing the Game Session (the reference timestamper uses sashite:session), following the same discovery pattern as per-Ply attestations — and, as there, the designated timestamper MUST include it (kind 3423 §Time accounting). NIP-26-delegated signatures from the timestamper are NOT accepted as authoritative.
In attested mode, the Conclusion’s own created_at is informational and MUST NOT be used for any timing-dependent decision; in self-timed mode it IS the canonical timing, made non-backdatable by the designated timing relay. See Canonical Timing.
Natural state of events at the cutoff
The verdict a Conclusion carries MUST be the outcome of the natural state of events at the cutoff: the Conclusion’s own canonical timing.
Specifically, the natural state consists of the longest consecutive chain of Plies following the session’s play order from its first half-move, where the Ply at each position satisfies all of the following:
- The Ply occupies the next slot in the play order. A Ply’s slot is
(session, signer, step), wherestepis the signer’s own move ordinal (kind3423§Step semantics and play order); the mapping from slots to the play order — where each player’s step k falls — is defined by the rule system for the session’s(game, variant). For many games the two players’ sequences strictly alternate within each step value, but a rule system MAY define a different interleaving, including turn structures where a player moves more than once in a row. - The Ply is canonical for its slot per Canonical Timing §Meta-resolution (or per the rule system’s selection among a slot’s candidates, where it defines one — kind
3423§Multiple Plies for the same step). - The Ply’s canonical timing is less than or equal to the cutoff.
- The Ply’s canonical timing is greater than or equal to t₀ (kind
3422§Canonical session start: the later of the Game Session’sstart_attag, when present, and its canonical timing). A Ply whose canonical timing precedes t₀ is invalid (kind3423§Time accounting: no Ply is valid before t₀) and MUST NOT enter the natural state.
Every rule-system question the chain raises — which candidate of a slot is legal, what the position is after a Ply, whether it is terminal, how the clocks are charged — and the resolution of the invocation when the chain ends in an ongoing position (who concluded, at what cutoff — the rule system’s post-chain conventions, such as an agreed draw, an abandonment timeout, or the residual resignation) are answered under the rule-system document the session was founded on, named by the Game Session’s rules tag (kind 3422 §Rules), and under no other. The concluding player has no latitude here: the natural state is a function of the public events, the signer, the cutoff and that document, which any party holding them can recompute — and constraint 8 makes agreement with that computation a condition of the Conclusion’s validity.
The chain stops at the first position in the play order for which no Ply satisfying all four conditions exists. Plies timed after the cutoff — canonical timing strictly greater than the cutoff — are excluded from the natural state. They MAY exist on Nostr and MAY become relevant for a later Conclusion with a later cutoff, but they do not contribute to this verdict.
Implications
- No post-conclusion racing: a player who plays additional moves after the opponent’s Conclusion cannot influence its verdict; only Plies whose canonical timing is at or before the cutoff are considered.
- Concluding is at the signer’s risk: the signer chooses when to conclude, never what the verdict is. A Conclusion published while the on-move opponent still has time, and while no termination stands, resolves under the reference rule system to the signer’s own resignation; a win-on-time claim cannot be voided by latency, since the cutoff is at or after the moment of publication and an expired clock only becomes more expired.
- Future-slot Plies activate by chain progression, not by signing time: a Ply timed for a slot the play order has not yet reached is excluded from the natural state until every prior position is part of the chain.
- No slot can be usurped: a Ply’s slot includes its signer, so no player can fill the other player’s position in the play order.
- Application-layer interpretation: the verdict’s content (the termination status) and result tags MUST reflect the natural state as defined above. Application-layer status vocabularies (e.g., the reference rule system’s Statuses — Sanki) interpret implicit termination conventions on this natural state, with the Conclusion’s signer as the invoker and its canonical timing as the cutoff.
Until the Conclusion has canonical timing
While the Conclusion has no canonical timing — in attested mode, not yet attested by the designated timestamper; in self-timed mode, not yet accepted by a designated timing relay — its cutoff is undefined and its verdict cannot be checked. Verifiers MUST treat such a Conclusion as pending — not yet effective as the session’s outcome, and not yet known to be conforming — until it acquires canonical timing (Canonical Timing §The pending state).
Tags
Reference tag
| Tag | Cardinality | Value | Description |
|---|---|---|---|
e game_session |
exactly one | event id, optional relay hint, marker | reference to the Game Session (kind 3422) for this session |
["e", "<game_session_event_id>", "<relay_hint>", "game_session"]— the Game Session event (kind3422) for this session. Exactly one such tag is required.
The relay hint (third element) is OPTIONAL but SHOULD be present.
Players
| Tag | Cardinality | Value | Description |
|---|---|---|---|
p |
exactly two | pubkey, optional relay hint, marker player |
a session player |
The two p tags identify the two session players, each with the marker player as its fourth element:
["p", "<player_pubkey>", "<relay_hint>", "player"]
The set of player pubkeys MUST match the players (the player-marked p tags) in the referenced Game Session (kind 3422); the signer is one of them. The p tags serve a dual purpose: semantic (identifying the two players) and structural (notification routing via standard Nostr #p filters — the opponent learns of the Conclusion through their own #p subscription).
Seats
| Tag | Cardinality | Value | Description |
|---|---|---|---|
seat |
exactly one per player | pubkey, seat-name | the player’s seat assignment |
The Conclusion MUST carry exactly one seat tag per player:
["seat", "<player_pubkey>", "<seat_name>"]
The seat-names are the protocol’s two values, first and second (kind 3420 §Match-terms tags), one per player. The set of seat tags MUST mirror those of the referenced Game Session: same player→seat mapping.
Outcome tags
| Tag | Cardinality | Value | Description |
|---|---|---|---|
result |
exactly two | pubkey + integer | result assigned to a player |
A result tag is structured ["result", "<pubkey>", "<integer>"]:
- The second element is the pubkey of one of the two players of the session.
- The third element is a non-negative integer matching the regular expression:
^(100|[1-9]?[0-9])$
This regex admits values from 0 through 99 (no leading zeros) and exactly 100. Values such as 00, 001, 101, or negative values are invalid.
The two result tags MUST reference the two different players. Their integer values MUST sum exactly to 100.
Common configurations:
100 / 0— decisive (one player wins, the other loses).50 / 50— draw.- Other integer combinations summing to
100are permitted but uncommon in classical chess-family rules.
Lifecycle tag
| Tag | Cardinality | Value | Description |
|---|---|---|---|
nonce |
exactly one | nonce + difficulty | NIP-13 proof of work |
The nonce tag follows NIP-13. Like the Ply, the Conclusion is a player-signed, clock-relevant event: the difficulty relays require for it SHOULD be kept low, since mining latency delays the cutoff and is borne by the signer.
Content
The content field MUST contain a termination status string identifying the cause of session termination, taken from the vocabulary defined by the application layer for the session’s rule system (e.g., Statuses — Sanki for the reference sanki rule system).
The content field MUST satisfy:
^[a-z]{1,32}$
That is: one to thirty-two lowercase ASCII letters (a–z), with no digits, no uppercase, no separators, no surrounding whitespace, and no JSON wrapping.
The content field MUST NOT carry any other data. A Conclusion carries no narrative payload: it states the rule system’s verdict, not the signer’s opinion of it. If a player wishes to publish commentary, they SHOULD use a separate event (e.g., a kind 1 note) referencing this Conclusion via an e tag.
Semantic constraints
A conforming Conclusion event MUST satisfy all of the following:
- The event contains exactly one
game_session-markedetag and no otheretag. - The
game_sessionetag references a retrievable, signature-valid, conforming Game Session event (kind3422, per its §Semantic constraints) that is the canonical Game Session for its slot (kind3422§Idempotence and race resolution). - The event’s
pubkey(the signer) MUST be one of theplayer-marked pubkeys of the referenced Game Session. - The event contains exactly two
ptags, each markedplayer, with distinct pubkeys, matching those of theplayer-markedptags in the referenced Game Session. - The event contains exactly one
seattag perptag, with pubkey matching one of the players and seat-namefirstorsecond(one each). Theseatassignments MUST mirror theseattags of the referenced Game Session. - The event contains exactly two
resulttags. Their second elements are the two different players’ pubkeys (as identified in theptags). Their third elements are non-negative integers matching^(100|[1-9]?[0-9])$, summing exactly to100. - The
contentfield is a non-empty string of one to thirty-two lowercase ASCII letters matching^[a-z]{1,32}$, with no surrounding whitespace and no additional data; and exactly onenoncetag is present, carries its committed difficulty as its third element, and the event id satisfies NIP-13 against that committed difficulty — never against a relay’s advertised minimum (an ingestion policy, not conformance). - Correctness. The event has canonical timing, and its
resulttags andcontentequal the outcome that the rule-system document named by the Game Session’srulestag yields for the natural state of the session at the cutoff (§Natural state of events at the cutoff), with the event’s signer as the invoker. A Conclusion stating any other outcome is non-conforming.
Constraints 1, 6 and 7 are checkable from the event alone. Constraints 2–5 require cross-event validation against the referenced Game Session. Constraint 8 requires the session’s Plies, their canonical timings, and the rule-system document: a consumer that does not hold the document can check constraints 1–7 only and MUST treat the Conclusion as unverified, never as conforming.
Validation responsibility
Validation of a Conclusion against the semantic constraints (§Semantic constraints) is the responsibility of every consumer that acts on it: the opponent’s client, observers, rating verifiers, and any client founding a rematch on it.
A Conclusion that fails any constraint — constraint 8 included — is invalid and does not terminate the session. The session remains open, and either player MAY publish a new Conclusion, at a new cutoff, stating the outcome the rule system then yields. A client SHOULD compute the verdict with a conforming implementation of the rule system before publishing, so that its Conclusions are never invalid.
The rule-system document being public and content-addressed, no party is trusted on the rules axis: a Conclusion is checked, not believed. What remains trusted is the timing authority whose acceptance or attestation confers the cutoff (Canonical Timing §Security). The fuller trust model belongs to the consuming application’s documentation (this suite’s application layer maintains one).
Idempotence and finality
A given session has exactly one canonical Conclusion — a per-session slot: because every conforming Conclusion must reference the session’s canonical Game Session (constraint 2), all of a session’s conforming Conclusions share one game_session reference, and competing ones land in one slot. The canonical event is the conforming candidate with the smallest canonical timing, with the smallest event ID as tiebreaker (Canonical Timing §Meta-resolution), whichever player signed it. Two conforming Conclusions with different cutoffs MAY carry different verdicts — a premature claim resolving to the claimant’s resignation at one cutoff, a timeout against the opponent at a later one — and the earliest one rules, at its signer’s risk. A non-conforming Conclusion does not occupy the slot: it has no effect, whatever its timing.
Non-canonical Conclusions MUST be ignored by clients as the session’s outcome. They are not retracted from relays; they are simply not effective. They are not thereby void as evidence: any conforming Conclusion of a session witnesses that the session is over, canonical or not — which is why a rematch challenge (kind 3420 §Rematch challenge) may name any of them in its concluded_by reference, while the outcome it implies remains the canonical Conclusion’s alone. In attested mode, the Conclusion’s own created_at MUST NOT be used for canonicalization; in self-timed mode it IS the canonical timing.
Once a canonical Conclusion is established (a conforming Conclusion with canonical timing — attested by the designated timestamper in attested mode, or accepted by a designated timing relay in self-timed mode), the session is terminated. No further events — including subsequent Plies or later Conclusions — can alter the outcome. Until a Conclusion has canonical timing, it is pending and the session is not yet formally terminated.
Examples
The examples below use placeholder pubkeys, event IDs, relay URLs, and timestamps for illustration.
Example 1 — Decisive verdict, published by the winner
Bob (seat second) has checkmated Alice; his client computes the verdict and he publishes:
{
"kind": 3425,
"pubkey": "<bob_pubkey>",
"created_at": 1700005100,
"tags": [
["e", "<game_session_event_id>", "wss://relay.example.com", "game_session"],
["p", "<alice_pubkey>", "wss://relay.example.com", "player"],
["p", "<bob_pubkey>", "wss://relay.example.com", "player"],
["seat", "<alice_pubkey>", "first"],
["seat", "<bob_pubkey>", "second"],
["result", "<alice_pubkey>", "0"],
["result", "<bob_pubkey>", "100"],
["nonce", "18211", "8"]
],
"content": "checkmate",
"id": "...",
"sig": "..."
}
Alice’s client, replaying the session under the rule system to cutoff 1700005100, reaches the same checkmate and the same result: the Conclusion is conforming and canonical. Had Alice published it herself — the loser concluding — the event would be identical but for its signer and would be equally valid.
Example 2 — Resignation
Alice, in a lost but not yet terminated position, resigns: she publishes a Conclusion whose verdict is the rule system’s residual reading of an invocation with no objective cause — her own loss (Statuses — Sanki §Implicit resignation):
{
"kind": 3425,
"pubkey": "<alice_pubkey>",
"created_at": 1700005100,
"tags": [
["e", "<game_session_event_id>", "wss://relay.example.com", "game_session"],
["p", "<alice_pubkey>", "wss://relay.example.com", "player"],
["p", "<bob_pubkey>", "wss://relay.example.com", "player"],
["seat", "<alice_pubkey>", "first"],
["seat", "<bob_pubkey>", "second"],
["result", "<alice_pubkey>", "0"],
["result", "<bob_pubkey>", "100"],
["nonce", "18211", "8"]
],
"content": "resignation",
"id": "...",
"sig": "..."
}
Had Alice’s client instead written ["result", "<alice_pubkey>", "100"] with content "timeout" while Bob’s clock had not expired, the Conclusion would fail constraint 8 and have no effect.
Example 3 — Draw
Bob offered a draw with the draw flag on his last Ply; Alice accepts by concluding — the rule system reads the offeree’s invocation, while the offer is the last move of the chain, as an agreement:
{
"kind": 3425,
"pubkey": "<alice_pubkey>",
"created_at": 1700005100,
"tags": [
["e", "<game_session_event_id>", "wss://relay.example.com", "game_session"],
["p", "<alice_pubkey>", "wss://relay.example.com", "player"],
["p", "<bob_pubkey>", "wss://relay.example.com", "player"],
["seat", "<alice_pubkey>", "first"],
["seat", "<bob_pubkey>", "second"],
["result", "<alice_pubkey>", "50"],
["result", "<bob_pubkey>", "50"],
["nonce", "18211", "8"]
],
"content": "agreement",
"id": "...",
"sig": "..."
}
Client guidelines
Clients implementing kind: 3425 SHOULD:
- Subscribe to kind
3425events with a#pfilter on the user’s pubkey to receive Conclusions of the user’s own sessions. - Subscribe to kind
3425events with an#efilter on Game Session event IDs to follow Conclusions of sessions of interest. - Validate received Conclusion events against all semantic constraints (§Semantic constraints) — constraint 8 with a conforming implementation of the session’s rule system — before treating them as binding; display an unverifiable Conclusion (rule-system document not held) as such.
- Apply the canonical resolution rule (§Idempotence and finality) when multiple Conclusions reference the same session.
- Treat a canonical Conclusion as final; ignore any subsequent events (Plies, later Conclusions) for the same session.
- Read user-visible session results from the
resulttags, not thecontentfield: thecontentcarries the cause of termination; theresulttags carry the outcome distribution. Relays index only single-letter tag names (NIP-01), soresultis not usable as a relay-side filter — fetch Conclusions by#e(session) or#p(player) and extract the outcome client-side. - Before publishing, compute the verdict at the intended cutoff with a conforming implementation, and surface the consequence to the user: the only unconditional “conclude” affordance SHOULD be resign; claim-style affordances (win on time, draw on the board, accept the draw) SHOULD be offered only when the client itself predicts the corresponding verdict from the same public events. When the board itself is terminal (checkmate, stalemate, a background draw), the client SHOULD publish the Conclusion on the user’s behalf, whichever player it serves — the winner has every reason to, and the loser loses nothing by it.
Security considerations
-
Signatures: Conclusion events are signed by a player. Receiving clients MUST verify signatures per NIP-01 and that the signer is a player of the referenced Game Session (constraint 3).
-
Cross-event validation and recomputation: A Conclusion is meaningful only in conjunction with the referenced Game Session, the session’s Plies and the rule-system document. Clients MUST retrieve them and recompute the verdict (constraint 8); a Conclusion that cannot be recomputed is unverified, never binding.
-
No trusted party on the rules axis: a verdict is binding by correctness, so no player can improve their outcome by concluding — a wrong Conclusion is invalid, a premature one resolves against its signer. What a Conclusion can do is fix the cutoff, which is why concluding early is at the signer’s risk and why the earliest conforming Conclusion rules.
-
Timing authority: the cutoff is the Conclusion’s canonical timing, conferred by the session’s timing authority. A timestamper or relay that backdates or delays it shifts the cutoff, which can change the verdict (the abandonment timeout in particular). This is the timing-authority discretion documented across the suite (Canonical Timing §Security), not a rules matter.
-
Idempotence: A session has exactly one canonical Conclusion; competing conforming Conclusions are resolved deterministically (§Idempotence and finality). Non-canonical Conclusions are ignored, not retracted; non-conforming ones never occupy the slot.
-
Finality: A canonical Conclusion terminates the session irreversibly. Clients MUST NOT process Plies or later Conclusions for a session that has a canonical Conclusion.
-
Time accounting: The clock accounting a verdict rests on uses the canonical timing of events (Canonical Timing): in attested mode, the Event Timestamp Attestations (kind
3410) signed by the designated timestamper (the events’ owncreated_atbeing informational); in self-timed mode, the events’ owncreated_at, made non-backdatable by the designated timing relay. -
Content validation: The
contentfield is normative — clients MUST validate it against^[a-z]{1,32}$, and against the rule system’s vocabulary and verdict (constraint 8). Any content failing these renders the event invalid as a Conclusion. -
Proof of work: the
noncetag limits Conclusion spam; since a Conclusion is clock-relevant, relays SHOULD keep its required difficulty low (§Lifecycle tag). -
Delegated signatures (NIP-26): NIP-26-delegated signatures are NOT accepted for Conclusions. Authoritative signatures MUST come directly from a player’s pubkey. See kind
3420§Security considerations for the suite’s general delegation policy.
References
- NIP-01 — Basic protocol flow description
- NIP-13 — Proof of Work
- Kind
3422— Game Session (the session being concluded) - Kind
3423— Ply (the events the natural state is computed from) - Kind
3420— Direct Challenge, §Rematch challenge (references a Conclusion of the concluded session, markedconcluded_by, as its structural proof that the session is over) - Kind
3426— Elo Rating Attestation — generic Elo signed-snapshot format that a rating authority MAY use to publish Elo ratings derived from this Conclusion - Kind
3427— Glicko-2 Rating Attestation — generic Glicko-2 signed-snapshot format that a rating authority MAY use to publish Glicko-2 ratings derived from this Conclusion - Event Timestamp Attestation — primitive for the Conclusion’s attestation (attested mode)
- Canonical Timing — canonical timing, the pending state, meta-resolution
