dev.superpipeline.gate.v2
A gate in the decision envelope: an m.room.message with a real body and the suite_event_type marker, beside the v1 card. Options are carried as the gate offers them; a client draws by meaning, never by id. A subject-bound gate carries its subject, a variant gate carries subject.variants with no identity of its own, and a quorum, release, checks or deadline only when they apply. Readers ignore properties they do not know. x-uniqueBy lists paths whose values must not repeat (JSON Schema cannot say so): a[].b is field b of each item of list a.
How it rides
Section titled “How it rides”An m.room.message whose content carries suite_event_type: "dev.superpipeline.gate.v2".
Who sends it, who reads it
Section titled “Who sends it, who reads it”- Sent by AgentPod, SuperExchange.
- Read by SuperMessage.
The carrier is whichever service carries the board’s chat: AgentPod’s hub, or SuperExchange for a board that has moved to it.
Fields
Section titled “Fields”| Field | Type | Required | Description | Constraints |
|---|---|---|---|---|
msgtype |
"m.text" |
yes | ||
body |
string | yes | ||
suite_event_type |
"dev.superpipeline.gate.v2" |
yes | ||
schema_version |
integer | yes | at least 1 | |
board_id |
string | yes | ||
card_id |
string | yes | ||
gate_id |
string | yes | at least 1 character | |
stage_key |
string | yes | ||
return_stage_key |
string | yes | ||
card_title |
string | yes | ||
produced_by |
string | yes | ||
prompt |
string | yes | ||
handoff_summary |
string | no | ||
options |
array of object | yes | at least 1 item; at most 20 items | |
options[].id |
string | yes | at least 1 character; at most 200 characters | |
options[].label |
string | yes | at most 200 characters | |
options[].meaning |
one of "approve", "reject", "revise", "choose", "defer" |
yes | ||
options[].needs_comment |
boolean | yes | ||
options[].delivery |
one of "automatic", "manual" |
no | ||
subject |
object (subject) or object (with variants) | no | ||
subject.id |
string | yes | in the subject shape; at least 1 character; at most 512 characters |
|
subject.digest |
string | yes | in the subject shape; at least 1 character; at most 512 characters |
|
subject.schema |
string | yes | in the subject shape; at least 1 character; at most 200 characters |
|
subject.revision |
integer | yes | in the subject shape; at least 0 |
|
subject.expires_at |
string or null | yes | When the binding lapses: an RFC 3339 date-time with seconds and an explicit offset (2030-01-02T03:04:05Z, 2030-01-02T08:34:05.5+05:30), or null for none. The pattern states it for a validator that does not assert format. | in the subject shape; format date-time; pattern ^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])T([01]\d|2[0-3]):[0-5]\d:[0-5]\d(\.\d+)?(Z|[+-]([01]\d|2[0-3]):[0-5]\d)$; at most 200 characters |
subject.preview |
array of object (type = “text”) or object (type = “field”) or object (type = “link”) | yes | in the subject shape; at most 20 items |
|
subject.preview[].type |
"text" |
yes | in the type = "text" shape |
|
subject.preview[].label |
string | no | in the type = "text" shape; at most 200 characters |
|
subject.preview[].text |
string | yes | in the type = "text" shape; at most 4000 characters |
|
subject.preview[].type |
"field" |
yes | in the type = "field" shape |
|
subject.preview[].label |
string | yes | in the type = "field" shape; at most 200 characters |
|
subject.preview[].value |
string | yes | in the type = "field" shape; at most 200 characters |
|
subject.preview[].type |
"link" |
yes | in the type = "link" shape |
|
subject.preview[].label |
string | yes | in the type = "link" shape; at most 200 characters |
|
subject.preview[].url |
string | yes | in the type = "link" shape; pattern ^https?://[^\s<>]+$; at most 4000 characters |
|
subject.preview_complete |
boolean | yes | in the subject shape |
|
subject.variants |
array of object | yes | in the with variants shape; at least 1 item; at most 3 items |
|
subject.variants[].id |
string | yes | in the with variants shape; at least 1 character; at most 64 characters |
|
subject.variants[].label |
string | yes | in the with variants shape; at least 1 character; at most 80 characters |
|
subject.variants[].subject |
object | yes | The exact thing an approving answer approves, re-bounded by the carrier. The sender still lists approving options when preview_complete is false; a client must not offer them, and the carrier refuses an approving answer to an incomplete preview. | in the with variants shape |
subject.variants[].subject.id |
string | yes | in the with variants shape; at least 1 character; at most 512 characters |
|
subject.variants[].subject.digest |
string | yes | in the with variants shape; at least 1 character; at most 512 characters |
|
subject.variants[].subject.schema |
string | yes | in the with variants shape; at least 1 character; at most 200 characters |
|
subject.variants[].subject.revision |
integer | yes | in the with variants shape; at least 0 |
|
subject.variants[].subject.expires_at |
string or null | yes | When the binding lapses: an RFC 3339 date-time with seconds and an explicit offset (2030-01-02T03:04:05Z, 2030-01-02T08:34:05.5+05:30), or null for none. The pattern states it for a validator that does not assert format. | in the with variants shape; format date-time; pattern ^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])T([01]\d|2[0-3]):[0-5]\d:[0-5]\d(\.\d+)?(Z|[+-]([01]\d|2[0-3]):[0-5]\d)$; at most 200 characters |
subject.variants[].subject.preview |
array of object (type = “text”) or object (type = “field”) or object (type = “link”) | yes | in the with variants shape; at most 20 items |
|
subject.variants[].subject.preview[].type |
"text" |
yes | in the type = "text" shape |
|
subject.variants[].subject.preview[].label |
string | no | in the type = "text" shape; at most 200 characters |
|
subject.variants[].subject.preview[].text |
string | yes | in the type = "text" shape; at most 4000 characters |
|
subject.variants[].subject.preview[].type |
"field" |
yes | in the type = "field" shape |
|
subject.variants[].subject.preview[].label |
string | yes | in the type = "field" shape; at most 200 characters |
|
subject.variants[].subject.preview[].value |
string | yes | in the type = "field" shape; at most 200 characters |
|
subject.variants[].subject.preview[].type |
"link" |
yes | in the type = "link" shape |
|
subject.variants[].subject.preview[].label |
string | yes | in the type = "link" shape; at most 200 characters |
|
subject.variants[].subject.preview[].url |
string | yes | in the type = "link" shape; pattern ^https?://[^\s<>]+$; at most 4000 characters |
|
subject.variants[].subject.preview_complete |
boolean | yes | in the with variants shape |
|
quorum |
object | no | ||
quorum.required |
integer | yes | at least 2; at most 5 | |
quorum.from |
one of "deciders", "admins" |
yes | ||
quorum.approvals |
array of object | yes | at most 32 items | |
quorum.approvals[].principal_id |
string | yes | at least 1 character; at most 128 characters | |
quorum.approvals[].at |
string | yes | pattern ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2}(\.\d{1,9})?)?(Z|[+-]\d{2}:\d{2})$; at most 40 characters |
|
quorum.approvals[].variant_id |
string | no | at least 1 character; at most 64 characters | |
release |
object | no | ||
release.hold_for_minutes |
integer | no | at least 5; at most 10080 | |
release.not_before |
string | no | pattern ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2}(\.\d{1,9})?)?(Z|[+-]\d{2}:\d{2})$; at most 40 characters |
|
checks |
array of object | no | at least 1 item; at most 5 items | |
checks[].name |
string | yes | pattern ^[^/\s]([^/]*[^/\s])?$; at least 1 character; at most 40 characters |
|
checks[].provider |
one of "ci", "verdict" |
yes | ||
checks[].status |
one of "pending", "passed", "failed", "overridden" |
yes | ||
checks[].url |
string | no | pattern ^https://[^\s<>]+$; at most 2048 characters |
|
deadline |
object | no | ||
deadline.remind_at |
string | no | pattern ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2}(\.\d{1,9})?)?(Z|[+-]\d{2}:\d{2})$; at most 40 characters |
|
deadline.escalate_at |
string | no | pattern ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2}(\.\d{1,9})?)?(Z|[+-]\d{2}:\d{2})$; at most 40 characters |
|
deep_link |
string | no |
x-uniqueBy: the values at these paths must not repeat, the one rule JSON Schema cannot state. a[].b is field b of each item of list a.
options[].idsubject.variants[].idsubject.variants[].subject.idquorum.approvals[].principal_idchecks[].name
Example
Section titled “Example”From fixtures/matrix-events/examples.json, case “a gate bound to a publishing subject: four options, the exact post in the preview and the body”:
{ "msgtype": "m.text", "body": "Approval needed — \"Announce the release\" at stage `approve`.\n\nPost:\n```\nOur next release ships today.\n\nThanks to everyone who tested it.\n```\n\nAccount: @fixture_account on X\n\nApproval expires: 2030-01-02T03:04:05Z\n\n[Open the card](https://superpipeline.dev/b/brd_7c1f/c/crd_6b40)", "suite_event_type": "dev.superpipeline.gate.v2", "schema_version": 1, "board_id": "brd_7c1f", "card_id": "crd_6b40", "gate_id": "gate_8f3a", "stage_key": "approve", "return_stage_key": "draft", "card_title": "Announce the release", "produced_by": "agt_31d0", "prompt": "Approve \"Announce the release\"?", "handoff_summary": "Our next release ships today.\n\nThanks to everyone who tested it.", "options": [ { "id": "approve_manual", "label": "Approve — I'll post it myself", "meaning": "approve", "needs_comment": false, "delivery": "manual" }, { "id": "approve_automatic", "label": "Approve — post automatically", "meaning": "approve", "needs_comment": false, "delivery": "automatic" }, { "id": "request_changes", "label": "Request changes", "meaning": "revise", "needs_comment": true }, { "id": "reject", "label": "Reject", "meaning": "reject", "needs_comment": false } ], "subject": { "id": "aps_2c9e71", "digest": "sha256:9b2f4e0c1a7d", "schema": "social-publish/v1", "revision": 1, "expires_at": "2030-01-02T03:04:05Z", "preview": [ { "type": "text", "label": "Post", "text": "Our next release ships today.\n\nThanks to everyone who tested it." }, { "type": "field", "label": "Account", "value": "@fixture_account on X" }, { "type": "field", "label": "Approval expires", "value": "2030-01-02T03:04:05Z" } ], "preview_complete": true }, "deep_link": "https://superpipeline.dev/b/brd_7c1f/c/crd_6b40"}The corpus has 14 valid cases in all:
an ordinary gate bound to no subject: no subject field, and the body is the v1 sentence
{ "msgtype": "m.text", "body": "Approval needed — \"Add OAuth login\" at stage `review`. Approve, request changes, or reject. [Open the card](https://superpipeline.dev/b/brd_7c1f/c/crd_9a22)", "suite_event_type": "dev.superpipeline.gate.v2", "schema_version": 1, "board_id": "brd_7c1f", "card_id": "crd_9a22", "gate_id": "gate_4e8b", "stage_key": "review", "return_stage_key": "code", "card_title": "Add OAuth login", "produced_by": "agt_31d0", "prompt": "Approve \"Add OAuth login\"?", "handoff_summary": "Added the OAuth routes and a test for the refresh-token path.", "options": [ { "id": "approve", "label": "Approve", "meaning": "approve", "needs_comment": false }, { "id": "request_changes", "label": "Request changes", "meaning": "revise", "needs_comment": true }, { "id": "reject", "label": "Reject", "meaning": "reject", "needs_comment": false } ], "deep_link": "https://superpipeline.dev/b/brd_7c1f/c/crd_9a22"}deadline: a gate with both deadlines
{ "msgtype": "m.text", "body": "Approval needed — \"Launch post\" at stage `review`. Approve, request changes, or reject. [Open the card](https://superpipeline.dev/b/brd_7c1f/c/crd_6b40)", "suite_event_type": "dev.superpipeline.gate.v2", "schema_version": 1, "board_id": "brd_7c1f", "card_id": "crd_6b40", "gate_id": "gate_8f3a", "stage_key": "review", "return_stage_key": "draft", "card_title": "Launch post", "produced_by": "agt_31d0", "prompt": "Approve \"Launch post\"?", "options": [ { "id": "approve", "label": "Approve", "meaning": "approve", "needs_comment": false }, { "id": "reject", "label": "Reject", "meaning": "reject", "needs_comment": false } ], "deadline": { "remind_at": "2026-11-08T15:00:00.000Z", "escalate_at": "2026-11-08T18:00:00.000Z" }, "deep_link": "https://superpipeline.dev/b/brd_7c1f/c/crd_6b40"}choice: three variants, the third cut to its share by the board and so incomplete on its own
{ "msgtype": "m.text", "body": "Choice needed — \"Announce the release\" at stage `approve`. Choose one of 3 versions.\n\n**Short**\n\nPost:\n```\nOur next release ships today.\n```\n\n**With the thread**\n\nPost:\n```\nOur next release ships today.\n\nThanks to everyone who tested it.\n```\n\n**Long form** — shortened here; choose it on the board.\n\nPost:\n```\nOur next release ships today. Here is everything in it, from the first…\n```\n\nTo choose, use an updated app or the board. [Open the card](https://superpipeline.dev/b/brd_7c1f/c/crd_7e31)", "suite_event_type": "dev.superpipeline.gate.v2", "schema_version": 1, "board_id": "brd_7c1f", "card_id": "crd_7e31", "gate_id": "gate_5d72", "stage_key": "approve", "return_stage_key": "draft", "card_title": "Announce the release", "produced_by": "agt_31d0", "prompt": "Choose a version of \"Announce the release\"", "handoff_summary": "Choose one of 3 variants: \"Short\", \"With the thread\", \"Long form\". Open the card to see them before approving.", "options": [ { "id": "approve_manual", "label": "Approve — I'll post it myself", "meaning": "approve", "needs_comment": false, "delivery": "manual" }, { "id": "approve_automatic", "label": "Approve — post automatically", "meaning": "approve", "needs_comment": false, "delivery": "automatic" }, { "id": "request_changes", "label": "Request changes", "meaning": "revise", "needs_comment": true }, { "id": "reject", "label": "Reject", "meaning": "reject", "needs_comment": false } ], "subject": { "variants": [ { "id": "short", "label": "Short", "subject": { "id": "aps_v1", "digest": "sha256:v1d1", "schema": "social-publish/v1", "revision": 1, "expires_at": "2030-01-02T03:04:05Z", "preview": [ { "type": "text", "label": "Post", "text": "Our next release ships today." } ], "preview_complete": true } }, { "id": "thread", "label": "With the thread", "subject": { "id": "aps_v2", "digest": "sha256:v2d1", "schema": "social-publish/v1", "revision": 2, "expires_at": "2030-01-02T03:04:05Z", "preview": [ { "type": "text", "label": "Post", "text": "Our next release ships today.\n\nThanks to everyone who tested it." } ], "preview_complete": true } }, { "id": "long", "label": "Long form", "subject": { "id": "aps_v3", "digest": "sha256:v3d1", "schema": "social-publish/v1", "revision": 3, "expires_at": "2030-01-02T03:04:05Z", "preview": [ { "type": "text", "label": "Post", "text": "Our next release ships today. Here is everything in it, from the first…" } ], "preview_complete": false } } ] }, "deep_link": "https://superpipeline.dev/b/brd_7c1f/c/crd_7e31"}quorum: a gate needing two of the workspace's owners and admins, one already recorded
{ "msgtype": "m.text", "body": "Approval needed — \"Ship the release\" at stage `release`. Approve, request changes, or reject. [Open the card](https://superpipeline.dev/b/brd_7c1f/c/crd_8a40)", "suite_event_type": "dev.superpipeline.gate.v2", "schema_version": 1, "board_id": "brd_7c1f", "card_id": "crd_8a40", "gate_id": "gate_6e19", "stage_key": "release", "return_stage_key": "build", "card_title": "Ship the release", "produced_by": "agt_31d0", "prompt": "Approve \"Ship the release\"?", "options": [ { "id": "approve", "label": "Approve", "meaning": "approve", "needs_comment": false }, { "id": "request_changes", "label": "Request changes", "meaning": "revise", "needs_comment": true }, { "id": "reject", "label": "Reject", "meaning": "reject", "needs_comment": false } ], "quorum": { "required": 2, "from": "admins", "approvals": [ { "principal_id": "prn_first", "at": "2026-11-09T10:00:00.000Z" } ] }, "deep_link": "https://superpipeline.dev/b/brd_7c1f/c/crd_8a40"}release: a stage that holds approvals for 30 minutes, on a subject that must not go out before Monday 09:00
{ "msgtype": "m.text", "body": "Approval needed — \"Ship the release\" at stage `release`. Approve, request changes, or reject. [Open the card](https://superpipeline.dev/b/brd_7c1f/c/crd_8a40)\n\nIf approved, it goes ahead after Mon 16 Nov, 09:00 UTC, and no sooner than 30 minutes after the approval.", "suite_event_type": "dev.superpipeline.gate.v2", "schema_version": 1, "board_id": "brd_7c1f", "card_id": "crd_8a40", "gate_id": "gate_6e19", "stage_key": "release", "return_stage_key": "build", "card_title": "Ship the release", "produced_by": "agt_31d0", "prompt": "Approve \"Ship the release\"?", "options": [ { "id": "approve", "label": "Approve", "meaning": "approve", "needs_comment": false }, { "id": "request_changes", "label": "Request changes", "meaning": "revise", "needs_comment": true }, { "id": "reject", "label": "Reject", "meaning": "reject", "needs_comment": false } ], "release": { "hold_for_minutes": 30, "not_before": "2026-11-16T09:00:00.000Z" }, "deep_link": "https://superpipeline.dev/b/brd_7c1f/c/crd_8a40"}release: a cooling-off period alone
{ "msgtype": "m.text", "body": "Approval needed — \"Ship the release\" at stage `release`. Approve, request changes, or reject. [Open the card](https://superpipeline.dev/b/brd_7c1f/c/crd_8a40)\n\nIf approved, it waits 30 minutes before it goes ahead.", "suite_event_type": "dev.superpipeline.gate.v2", "schema_version": 1, "board_id": "brd_7c1f", "card_id": "crd_8a40", "gate_id": "gate_6e19", "stage_key": "release", "return_stage_key": "build", "card_title": "Ship the release", "produced_by": "agt_31d0", "prompt": "Approve \"Ship the release\"?", "options": [ { "id": "approve", "label": "Approve", "meaning": "approve", "needs_comment": false }, { "id": "request_changes", "label": "Request changes", "meaning": "revise", "needs_comment": true }, { "id": "reject", "label": "Reject", "meaning": "reject", "needs_comment": false } ], "release": { "hold_for_minutes": 30 }, "deep_link": "https://superpipeline.dev/b/brd_7c1f/c/crd_8a40"}release: an embargo alone
{ "msgtype": "m.text", "body": "Approval needed — \"Ship the release\" at stage `release`. Approve, request changes, or reject. [Open the card](https://superpipeline.dev/b/brd_7c1f/c/crd_8a40)\n\nIf approved, it goes ahead after Mon 16 Nov, 09:00 UTC.", "suite_event_type": "dev.superpipeline.gate.v2", "schema_version": 1, "board_id": "brd_7c1f", "card_id": "crd_8a40", "gate_id": "gate_6e19", "stage_key": "release", "return_stage_key": "build", "card_title": "Ship the release", "produced_by": "agt_31d0", "prompt": "Approve \"Ship the release\"?", "options": [ { "id": "approve", "label": "Approve", "meaning": "approve", "needs_comment": false }, { "id": "request_changes", "label": "Request changes", "meaning": "revise", "needs_comment": true }, { "id": "reject", "label": "Reject", "meaning": "reject", "needs_comment": false } ], "release": { "not_before": "2026-11-16T09:00:00.000Z" }, "deep_link": "https://superpipeline.dev/b/brd_7c1f/c/crd_8a40"}checks: three checks passed or overridden before the gate opened
{ "msgtype": "m.text", "body": "Approval needed — \"Ship the release\" at stage `review`. Approve, request changes, or reject. [Open the card](https://superpipeline.dev/b/brd_7c1f/c/crd_8a40)\n\nChecks: build (CI) ✓, quality (verdict) ✓, claims (verdict) overridden.", "suite_event_type": "dev.superpipeline.gate.v2", "schema_version": 1, "board_id": "brd_7c1f", "card_id": "crd_8a40", "gate_id": "gate_6e19", "stage_key": "review", "return_stage_key": "build", "card_title": "Ship the release", "produced_by": "agt_31d0", "prompt": "Approve \"Ship the release\"?", "options": [ { "id": "approve", "label": "Approve", "meaning": "approve", "needs_comment": false }, { "id": "request_changes", "label": "Request changes", "meaning": "revise", "needs_comment": true }, { "id": "reject", "label": "Reject", "meaning": "reject", "needs_comment": false } ], "checks": [ { "name": "build", "provider": "ci", "status": "passed", "url": "https://forge.example/acme/app/actions/runs/412" }, { "name": "quality", "provider": "verdict", "status": "passed" }, { "name": "claims", "provider": "verdict", "status": "overridden" } ], "deep_link": "https://superpipeline.dev/b/brd_7c1f/c/crd_8a40"}built: a gate bound to no subject
{ "msgtype": "m.text", "body": "Approval needed — \"Ship the release notes\" at stage `review`. Approve, request changes, or reject. [Open the card](https://superpipeline.dev/b/brd_7c1f/c/crd_6b40)", "suite_event_type": "dev.superpipeline.gate.v2", "schema_version": 1, "board_id": "brd_7c1f", "card_id": "crd_6b40", "gate_id": "gate_8f3a", "stage_key": "review", "return_stage_key": "draft", "card_title": "Ship the release notes", "produced_by": "agt_31d0", "prompt": "Approve \"Ship the release notes\"?", "handoff_summary": "Release notes for 0.4, three sections.", "options": [ { "id": "approve", "label": "Approve", "meaning": "approve", "needs_comment": false }, { "id": "request_changes", "label": "Request changes", "meaning": "revise", "needs_comment": true }, { "id": "reject", "label": "Reject", "meaning": "reject", "needs_comment": false } ], "deep_link": "https://superpipeline.dev/b/brd_7c1f/c/crd_6b40"}built: a publishing gate bound to a subject
{ "msgtype": "m.text", "body": "Approval needed — \"Ship the release notes\" at stage `review`.\n\nPost:\n```\nOur next release ships today.\n```\n\nAccount: @fixture_account on X\n\n[Open the card](https://superpipeline.dev/b/brd_7c1f/c/crd_6b40)", "suite_event_type": "dev.superpipeline.gate.v2", "schema_version": 1, "board_id": "brd_7c1f", "card_id": "crd_6b40", "gate_id": "gate_8f3a", "stage_key": "review", "return_stage_key": "draft", "card_title": "Ship the release notes", "produced_by": "agt_31d0", "prompt": "Approve \"Ship the release notes\"?", "handoff_summary": "Release notes for 0.4, three sections.", "options": [ { "id": "approve_manual", "label": "Approve — I'll post it myself", "meaning": "approve", "needs_comment": false, "delivery": "manual" }, { "id": "approve_automatic", "label": "Approve — post automatically", "meaning": "approve", "needs_comment": false, "delivery": "automatic" }, { "id": "request_changes", "label": "Request changes", "meaning": "revise", "needs_comment": true }, { "id": "reject", "label": "Reject", "meaning": "reject", "needs_comment": false } ], "subject": { "id": "sub_post_1", "digest": "sha256:9a1e", "schema": "x-post/v1", "revision": 1, "expires_at": "2030-01-02T03:04:05Z", "preview": [ { "type": "text", "label": "Post", "text": "Our next release ships today." }, { "type": "field", "label": "Account", "value": "@fixture_account on X" } ], "preview_complete": true }, "deep_link": "https://superpipeline.dev/b/brd_7c1f/c/crd_6b40"}built: a subject whose preview the board cut: no approving option
{ "msgtype": "m.text", "body": "Approval needed — \"Ship the release notes\" at stage `review`.\n\nPost:\n```\nOur next release ships today.\n```\n\nAccount: @fixture_account on X", "suite_event_type": "dev.superpipeline.gate.v2", "schema_version": 1, "board_id": "brd_7c1f", "card_id": "crd_6b40", "gate_id": "gate_8f3a", "stage_key": "review", "return_stage_key": "draft", "card_title": "Ship the release notes", "produced_by": "agt_31d0", "prompt": "Approve \"Ship the release notes\"?", "handoff_summary": "Release notes for 0.4, three sections.", "options": [ { "id": "approve_manual", "label": "Approve — I'll post it myself", "meaning": "approve", "needs_comment": false, "delivery": "manual" }, { "id": "approve_automatic", "label": "Approve — post automatically", "meaning": "approve", "needs_comment": false, "delivery": "automatic" }, { "id": "request_changes", "label": "Request changes", "meaning": "revise", "needs_comment": true }, { "id": "reject", "label": "Reject", "meaning": "reject", "needs_comment": false } ], "subject": { "id": "sub_post_1", "digest": "sha256:9a1e", "schema": "x-post/v1", "revision": 1, "expires_at": "2030-01-02T03:04:05Z", "preview": [ { "type": "text", "label": "Post", "text": "Our next release ships today." }, { "type": "field", "label": "Account", "value": "@fixture_account on X" } ], "preview_complete": false }}built: a choice of two variants
{ "msgtype": "m.text", "body": "Choice needed — \"Ship the release notes\" at stage `review`. Choose one of 2 versions.\n\n**Short**\n\nPost:\n```\nOur next release ships today.\n```\n\nAccount: @fixture_account on X\n\n**Long form**\n\nPost:\n```\nOur next release ships today.\n```\n\nAccount: @fixture_account on X\n\nTo choose, use an updated app or the board. [Open the card](https://superpipeline.dev/b/brd_7c1f/c/crd_6b40)", "suite_event_type": "dev.superpipeline.gate.v2", "schema_version": 1, "board_id": "brd_7c1f", "card_id": "crd_6b40", "gate_id": "gate_8f3a", "stage_key": "review", "return_stage_key": "draft", "card_title": "Ship the release notes", "produced_by": "agt_31d0", "prompt": "Choose a version of \"Ship the release notes\"", "handoff_summary": "Release notes for 0.4, three sections.", "options": [ { "id": "approve_manual", "label": "Approve — I'll post it myself", "meaning": "approve", "needs_comment": false, "delivery": "manual" }, { "id": "approve_automatic", "label": "Approve — post automatically", "meaning": "approve", "needs_comment": false, "delivery": "automatic" }, { "id": "request_changes", "label": "Request changes", "meaning": "revise", "needs_comment": true }, { "id": "reject", "label": "Reject", "meaning": "reject", "needs_comment": false } ], "subject": { "variants": [ { "id": "short", "label": "Short", "subject": { "id": "sub_short", "digest": "sha256:9a1e", "schema": "x-post/v1", "revision": 1, "expires_at": "2030-01-02T03:04:05Z", "preview": [ { "type": "text", "label": "Post", "text": "Our next release ships today." }, { "type": "field", "label": "Account", "value": "@fixture_account on X" } ], "preview_complete": true } }, { "id": "long", "label": "Long form", "subject": { "id": "sub_long", "digest": "sha256:77aa", "schema": "x-post/v1", "revision": 1, "expires_at": "2030-01-02T03:04:05Z", "preview": [ { "type": "text", "label": "Post", "text": "Our next release ships today." }, { "type": "field", "label": "Account", "value": "@fixture_account on X" } ], "preview_complete": true } } ] }, "deep_link": "https://superpipeline.dev/b/brd_7c1f/c/crd_6b40"}built: a quorum, a hold, checks and a deadline together
{ "msgtype": "m.text", "body": "Approval needed — \"Ship the release notes\" at stage `review`. Approve, request changes, or reject. [Open the card](https://superpipeline.dev/b/brd_7c1f/c/crd_6b40)\n\nChecks: build (CI) ✓, claims (verdict) overridden.\n\nIf approved, it goes ahead after Wed 2 Jan, 09:00 UTC, and no sooner than 30 minutes after the approval.", "suite_event_type": "dev.superpipeline.gate.v2", "schema_version": 1, "board_id": "brd_7c1f", "card_id": "crd_6b40", "gate_id": "gate_8f3a", "stage_key": "review", "return_stage_key": "draft", "card_title": "Ship the release notes", "produced_by": "agt_31d0", "prompt": "Approve \"Ship the release notes\"?", "handoff_summary": "Release notes for 0.4, three sections.", "options": [ { "id": "approve", "label": "Approve", "meaning": "approve", "needs_comment": false }, { "id": "request_changes", "label": "Request changes", "meaning": "revise", "needs_comment": true }, { "id": "reject", "label": "Reject", "meaning": "reject", "needs_comment": false } ], "quorum": { "required": 2, "from": "deciders", "approvals": [ { "principal_id": "prn_00e5464a206549ff8c78", "at": "2030-01-01T09:00:00.000Z" } ] }, "release": { "hold_for_minutes": 30, "not_before": "2030-01-02T09:00:00Z" }, "checks": [ { "name": "build", "provider": "ci", "status": "passed", "url": "https://ci.example/run/1" }, { "name": "claims", "provider": "verdict", "status": "overridden" } ], "deadline": { "remind_at": "2030-01-01T12:00:00Z", "escalate_at": "2030-01-02T09:00:00Z" }, "deep_link": "https://superpipeline.dev/b/brd_7c1f/c/crd_6b40"}Refused
Section titled “Refused”Each of these must fail. The corpus says why:
- an option with no meaning. A sender must say what each option means; only a carrier projecting an older board derives it, and then it sends the derived value. (refused by
schema) - a subject with no digest. The answer must copy the digest back, and superpipeline binds the decision to it. (refused by
schema) - no body. A stock client would show nothing. (refused by
schema) - duplicate option ids. Answering is by id. (refused by
unique) - camelCase on the Matrix wire.
needsCommentis the board’s push field; the Matrix field isneeds_comment. (refused byschema) - deadline: deadline in the board’s camelCase. The envelope is snake_case. (refused by
schema) - deadline: a deadline that is not a time (refused by
schema) - deadline: an empty deadline. Absent means no timeout; an empty object means nothing. (refused by
schema) - choice: four variants. At most three (operator ruling, 2026-11-09). (refused by
schema) - choice: an id and digest beside the variants. A client that predates variants would read it as an ordinary subject and offer to approve something that is not the choice. (refused by
schema) - choice: a variant whose subject has no digest. The chosen variant’s digest is the binding. (refused by
schema) - choice: two variants sharing an id. A choice is made by variant; two with one id are an ambiguous answer. (refused by
unique) - quorum: required below 2: a gate that passes on one approval carries no quorum (refused by
schema) - quorum: required above 5 (refused by
schema) - quorum: from is neither deciders nor admins (refused by
schema) - quorum: an approval with no time (refused by
schema) - quorum: the same person counted twice (refused by
unique) - release: hold_for_minutes below 5 (refused by
schema) - release: hold_for_minutes above 7 days (refused by
schema) - release: hold_for_minutes not a whole number (refused by
schema) - release: not_before not an ISO time (refused by
schema) - release: a good not_before beside a bad hold is not carried in part (refused by
schema) - release: neither half (refused by
schema) - checks: an empty list (refused by
schema) - checks: more than 5 checks (refused by
schema) - checks: a name with a slash (it is a path segment of the override route) (refused by
schema) - checks: a name longer than 40 characters (refused by
schema) - checks: a name with surrounding spaces (refused by
schema) - checks: an unknown provider (refused by
schema) - checks: an unknown status (refused by
schema) - checks: two checks of one name (refused by
unique) - a subject revision that is not a whole number (refused by
schema) - an expiry that is a date only (refused by
schema) - an expiry written as a person would (refused by
schema) - an expiry with no offset (refused by
schema) - an expiry with no seconds (refused by
schema) - an expiry with a space for the T (refused by
schema) - an expiry whose offset has no colon (refused by
schema) - an expiry in lower case (refused by
schema) - an expiry on a day the month does not have (refused by
schema) - no options: nothing to answer with (refused by
schema)
Source
Section titled “Source”- Schema:
schemas/matrix/dev.superpipeline.gate.v2.json - In the package:
import schema from "@superjackfruitlabs/treaty-matrix-events/schemas/dev.superpipeline.gate.v2.json" with { type: "json" };