Skip to content

gate.pending v1

A gate is waiting on a person (charter: a gate closes over chat; gate.v2). Pushed by SuperPipeline, and read back by the carrier’s sweep from GET /v1/boards/:id/gates/pending, from one builder. Mirrors SuperPipeline’s GatePendingBody (apps/api/src/board/views.ts). Readers ignore properties they do not know.

Every event below carries dataschema https://raw.githubusercontent.com/SuperJackfruitLabs/treaty/main/schemas/superpipeline/gate.pending.v1.json.

Body event CloudEvents type Subject
gate.pending com.superjackfruit.superpipeline.gate.pending.v1 evt.<workspace>.superpipeline.gate.pending

The subject is the NATS subject the relay files it under; <workspace> is the board’s workspace. See the envelope and subjects.

  • Produced by SuperPipeline, through the relay.
  • Consumed by:
    • SuperExchange: Posts it to the board’s room, for the boards it carries. Receives it through the relay.
    • AgentPod: The hub’s board chat posts it, for the boards it still carries.
    • SuperDispatch: Takes it as a nudge to look at the board soon, on a board opted into scheduling. Reads nothing from its data.

Readers ignore properties they do not know, so a field may be added without a new version.

Field Type Required Description Constraints
event "gate.pending" yes
boardId string or null yes
boardName string yes What the board is called; empty string when it has no name, never absent.
cardId string yes
gateId string yes
stageKey string yes
returnStageKey string yes
cardTitle string yes
producedBy string yes
handoffSummary string or null yes What the reviewer is asked to approve; null for a gate with no handoff.
approvalSubject object (subject) or object (variantSubjects) no
approvalSubject.id string yes in the subject shape
approvalSubject.digest string yes in the subject shape
approvalSubject.schema string yes in the subject shape
approvalSubject.revision integer yes in the subject shape; at least 0
approvalSubject.expiresAt string or null yes in the subject shape
approvalSubject.preview array of object (type = “text”) or object (type = “field”) or object (type = “link”) yes in the subject shape
approvalSubject.preview[].type "text" yes in the type = "text" shape
approvalSubject.preview[].label string no in the type = "text" shape
approvalSubject.preview[].text string yes in the type = "text" shape
approvalSubject.preview[].type "field" yes in the type = "field" shape
approvalSubject.preview[].label string yes in the type = "field" shape
approvalSubject.preview[].value string yes in the type = "field" shape
approvalSubject.preview[].type "link" yes in the type = "link" shape
approvalSubject.preview[].label string yes in the type = "link" shape
approvalSubject.preview[].url string yes in the type = "link" shape
approvalSubject.previewComplete boolean yes False when the preview was cut to its bounds; no approving option may then be offered. in the subject shape
approvalSubject.variants array of object yes in the variantSubjects shape; at least 1 item
approvalSubject.variants[].id string yes in the variantSubjects shape
approvalSubject.variants[].label string yes in the variantSubjects shape
approvalSubject.variants[].subject object yes A subject as a decision envelope carries it (gate.v2 §3): identity, expiry and the kind’s bounded preview. The canonical payload stays behind the authenticated route. in the variantSubjects shape
approvalSubject.variants[].subject.id string yes in the variantSubjects shape
approvalSubject.variants[].subject.digest string yes in the variantSubjects shape
approvalSubject.variants[].subject.schema string yes in the variantSubjects shape
approvalSubject.variants[].subject.revision integer yes in the variantSubjects shape; at least 0
approvalSubject.variants[].subject.expiresAt string or null yes in the variantSubjects shape
approvalSubject.variants[].subject.preview array of object (type = “text”) or object (type = “field”) or object (type = “link”) yes in the variantSubjects shape
approvalSubject.variants[].subject.preview[].type "text" yes in the type = "text" shape
approvalSubject.variants[].subject.preview[].label string no in the type = "text" shape
approvalSubject.variants[].subject.preview[].text string yes in the type = "text" shape
approvalSubject.variants[].subject.preview[].type "field" yes in the type = "field" shape
approvalSubject.variants[].subject.preview[].label string yes in the type = "field" shape
approvalSubject.variants[].subject.preview[].value string yes in the type = "field" shape
approvalSubject.variants[].subject.preview[].type "link" yes in the type = "link" shape
approvalSubject.variants[].subject.preview[].label string yes in the type = "link" shape
approvalSubject.variants[].subject.preview[].url string yes in the type = "link" shape
approvalSubject.variants[].subject.previewComplete boolean yes False when the preview was cut to its bounds; no approving option may then be offered. in the variantSubjects shape
reviewUrl string no Authenticated web route for reviewing the authoritative subject.
options array of object yes
options[].id string yes
options[].label string yes
options[].meaning one of "approve", "reject", "revise", "choose", "defer" yes What choosing the option does (gate.v2 §2).
options[].needsComment boolean yes
options[].delivery one of "automatic", "manual" no Only on an option that approves a subject.
deadline object no When the decision is reminded about and escalated. Absent when its stage sets no timeout.
deadline.remindAt string no format date-time
deadline.escalateAt string no format date-time
quorum object no A quorum gate’s progress; absent on a gate one approval passes.
quorum.required integer yes at least 1
quorum.from one of "deciders", "admins" yes
quorum.approvals array of object yes
quorum.approvals[].principalId string yes
quorum.approvals[].at string yes format date-time
quorum.approvals[].variantId string no
release object no What holds an approval before it acts; absent when nothing does.
release.holdForMinutes integer no at least 0
release.notBefore string no format date-time
checks array of object no The checks that ran before the gate opened; absent when the stage has none.
checks[].name string yes
checks[].provider one of "ci", "verdict" yes
checks[].status one of "pending", "passed", "failed", "overridden" yes
checks[].url string no
ts string yes When the gate opened, on the gate’s own clock, so a re-read is byte-identical. format date-time

From fixtures/superpipeline-events/examples.json, case “plain”:

{
"event": "gate.pending",
"boardId": "brd_134a0ddb6d434478",
"boardName": "Developer Experience",
"cardId": "crd_0f3c9a2b7d4e4a11",
"gateId": "gte_5a1b2c3d4e5f6071",
"stageKey": "review",
"returnStageKey": "research",
"cardTitle": "Research this",
"producedBy": "agt_9e8d7c6b5a493827",
"handoffSummary": "Two sources.",
"options": [
{
"id": "approve",
"label": "Approve",
"meaning": "approve",
"needsComment": false
},
{
"id": "request_changes",
"label": "Request changes",
"meaning": "revise",
"needsComment": true
},
{
"id": "reject",
"label": "Reject",
"meaning": "reject",
"needsComment": false
}
],
"ts": "2026-11-10T09:30:00.000Z"
}

The corpus has 5 valid cases in all:

subject-bound
{
"event": "gate.pending",
"boardId": "brd_134a0ddb6d434478",
"boardName": "Developer Experience",
"cardId": "crd_0f3c9a2b7d4e4a11",
"gateId": "gte_5a1b2c3d4e5f6071",
"stageKey": "review",
"returnStageKey": "research",
"cardTitle": "Research this",
"producedBy": "agt_9e8d7c6b5a493827",
"handoffSummary": "Two sources.",
"options": [
{
"id": "approve_automatic",
"label": "Approve and post",
"meaning": "approve",
"needsComment": false,
"delivery": "automatic"
},
{
"id": "approve_manual",
"label": "Approve, I'll post it",
"meaning": "approve",
"needsComment": false,
"delivery": "manual"
},
{
"id": "request_changes",
"label": "Request changes",
"meaning": "revise",
"needsComment": true
},
{
"id": "reject",
"label": "Reject",
"meaning": "reject",
"needsComment": false
}
],
"ts": "2026-11-10T09:30:00.000Z",
"approvalSubject": {
"id": "sub_7d6c5b4a39281706",
"digest": "sha256:4f2a0c1e9b8d7f6a5e4d3c2b1a09f8e7d6c5b4a39281706f5e4d3c2b1a09f8e7",
"schema": "social-publish/v1",
"revision": 1,
"expiresAt": "2026-11-11T09:30:00.000Z",
"preview": [
{
"type": "text",
"label": "Post",
"text": "We shipped the decision envelope."
},
{
"type": "field",
"label": "Account",
"value": "@example"
},
{
"type": "link",
"label": "Draft",
"url": "https://example.com/draft"
}
],
"previewComplete": true
},
"reviewUrl": "https://app.superpipeline.dev/b/brd_134a0ddb6d434478/c/crd_0f3c9a2b7d4e4a11/review"
}
variants
{
"event": "gate.pending",
"boardId": "brd_134a0ddb6d434478",
"boardName": "Developer Experience",
"cardId": "crd_0f3c9a2b7d4e4a11",
"gateId": "gte_5a1b2c3d4e5f6071",
"stageKey": "review",
"returnStageKey": "research",
"cardTitle": "Research this",
"producedBy": "agt_9e8d7c6b5a493827",
"handoffSummary": "Two sources.",
"options": [
{
"id": "choose",
"label": "Choose a variant",
"meaning": "choose",
"needsComment": false
},
{
"id": "reject",
"label": "Reject",
"meaning": "reject",
"needsComment": false
}
],
"ts": "2026-11-10T09:30:00.000Z",
"approvalSubject": {
"variants": [
{
"id": "short",
"label": "Short",
"subject": {
"id": "sub_7d6c5b4a39281706",
"digest": "sha256:4f2a0c1e9b8d7f6a5e4d3c2b1a09f8e7d6c5b4a39281706f5e4d3c2b1a09f8e7",
"schema": "social-publish/v1",
"revision": 1,
"expiresAt": "2026-11-11T09:30:00.000Z",
"preview": [
{
"type": "text",
"label": "Post",
"text": "We shipped the decision envelope."
},
{
"type": "field",
"label": "Account",
"value": "@example"
},
{
"type": "link",
"label": "Draft",
"url": "https://example.com/draft"
}
],
"previewComplete": true
}
},
{
"id": "long",
"label": "Long",
"subject": {
"id": "sub_8e7d6c5b4a392817",
"digest": "sha256:4f2a0c1e9b8d7f6a5e4d3c2b1a09f8e7d6c5b4a39281706f5e4d3c2b1a09f8e7",
"schema": "social-publish/v1",
"revision": 1,
"expiresAt": "2026-11-11T09:30:00.000Z",
"preview": [
{
"type": "text",
"label": "Post",
"text": "We shipped the decision envelope."
},
{
"type": "field",
"label": "Account",
"value": "@example"
},
{
"type": "link",
"label": "Draft",
"url": "https://example.com/draft"
}
],
"previewComplete": true
}
}
]
}
}
deadline-quorum-release-checks
{
"event": "gate.pending",
"boardId": "brd_134a0ddb6d434478",
"boardName": "Developer Experience",
"cardId": "crd_0f3c9a2b7d4e4a11",
"gateId": "gte_5a1b2c3d4e5f6071",
"stageKey": "review",
"returnStageKey": "research",
"cardTitle": "Research this",
"producedBy": "agt_9e8d7c6b5a493827",
"handoffSummary": "Two sources.",
"options": [
{
"id": "approve",
"label": "Approve",
"meaning": "approve",
"needsComment": false
},
{
"id": "request_changes",
"label": "Request changes",
"meaning": "revise",
"needsComment": true
},
{
"id": "reject",
"label": "Reject",
"meaning": "reject",
"needsComment": false
}
],
"ts": "2026-11-10T09:30:00.000Z",
"deadline": {
"remindAt": "2026-11-10T13:30:00.000Z",
"escalateAt": "2026-11-11T09:30:00.000Z"
},
"quorum": {
"required": 2,
"from": "deciders",
"approvals": [
{
"principalId": "prn_0123456789abcdef0123",
"at": "2026-11-10T10:00:00.000Z"
}
]
},
"release": {
"holdForMinutes": 30,
"notBefore": "2026-11-10T12:00:00.000Z"
},
"checks": [
{
"name": "ci / test",
"provider": "ci",
"status": "passed",
"url": "https://forge.example.com/runs/1"
},
{
"name": "tone",
"provider": "verdict",
"status": "overridden"
}
]
}
no-board-name-no-handoff
{
"event": "gate.pending",
"boardId": null,
"boardName": "",
"cardId": "crd_0f3c9a2b7d4e4a11",
"gateId": "gte_5a1b2c3d4e5f6071",
"stageKey": "review",
"returnStageKey": "research",
"cardTitle": "Research this",
"producedBy": "agt_9e8d7c6b5a493827",
"handoffSummary": null,
"options": [
{
"id": "approve",
"label": "Approve",
"meaning": "approve",
"needsComment": false
},
{
"id": "request_changes",
"label": "Request changes",
"meaning": "revise",
"needsComment": true
},
{
"id": "reject",
"label": "Reject",
"meaning": "reject",
"needsComment": false
}
],
"ts": "2026-11-10T09:30:00.000Z"
}

Each of these must fail. The corpus says why:

  • boardName is never absent
  • an option’s meaning is one of five
  • a variant gate carries no top-level id
  • ts is a date-time
  • a subject says whether its preview is complete
  • the event names itself