Skip to content

dev.superpipeline.gate.v1

The legacy custom event a v1 gate is sent as beside its prose message: the embedded card plus body. 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.

A custom Matrix event of type dev.superpipeline.gate.v1, sent beside its prose message.

The carrier is whichever service carries the board’s chat: AgentPod’s hub, or SuperExchange for a board that has moved to it.

Field Type Required Description Constraints
body string 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 3 items
options[].id one of "approve", "request_changes", "reject" yes
options[].label string yes
deep_link string no

The schema also states these rules across fields, as written:

{
"allOf": [
{
"description": "Fields dropped deliberately (tenant_id, run_id, task_id, expires_at): a sender that has them was built against a superseded sketch.",
"not": {
"anyOf": [
{
"required": [
"tenant_id"
]
},
{
"required": [
"run_id"
]
},
{
"required": [
"task_id"
]
},
{
"required": [
"expires_at"
]
}
]
}
}
]
}

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[].id

From fixtures/matrix-events/examples.json, case “the ordinary case”:

{
"body": "Approval needed — \"Add OAuth login\" at stage `review`. Approve, request changes, or reject: https://superpipeline.dev/b/brd_7c1f/c/crd_9a22",
"schema_version": 2,
"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": "Ship the OAuth change to staging?",
"options": [
{
"id": "approve",
"label": "Approve"
},
{
"id": "request_changes",
"label": "Request changes"
},
{
"id": "reject",
"label": "Reject"
}
],
"deep_link": "https://superpipeline.dev/b/brd_7c1f/c/crd_9a22",
"handoff_summary": "Added the OAuth routes and a test for the refresh-token path."
}

The corpus has 5 valid cases in all:

a higher schema_version is tolerated — a v1 renderer reads the fields it knows and ignores the rest
{
"body": "Approval needed — \"Rotate the signing key\" at stage `review`.",
"schema_version": 2,
"board_id": "brd_7c1f",
"card_id": "crd_0011",
"gate_id": "gate_0012",
"stage_key": "review",
"return_stage_key": "prepare",
"card_title": "Rotate the signing key",
"produced_by": "agt_31d0",
"prompt": "Rotate now?",
"options": [
{
"id": "approve",
"label": "Rotate"
},
{
"id": "reject",
"label": "Not yet"
}
],
"a_field_from_the_future": "ignored, not fatal"
}
two options rather than three — a gate need not offer request_changes
{
"body": "Approval needed — \"Delete the staging bucket\" at stage `review`.",
"schema_version": 1,
"board_id": "brd_7c1f",
"card_id": "crd_5150",
"gate_id": "gate_5151",
"stage_key": "review",
"return_stage_key": "plan",
"card_title": "Delete the staging bucket",
"produced_by": "agt_31d0",
"prompt": "This cannot be undone. Proceed?",
"options": [
{
"id": "approve",
"label": "Delete it"
},
{
"id": "reject",
"label": "Cancel"
}
]
}
choice: the variant gate above, as a v1 client sees it
{
"body": "Choice needed — \"Announce the release\" at stage `approve`. Choose a version in an updated app or on the board; request changes or reject can be sent from here. [Open the card](https://superpipeline.dev/b/brd_7c1f/c/crd_7e31)",
"schema_version": 2,
"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": "request_changes",
"label": "Request changes"
},
{
"id": "reject",
"label": "Reject"
}
],
"deep_link": "https://superpipeline.dev/b/brd_7c1f/c/crd_7e31"
}
built: a gate bound to no subject
{
"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)",
"schema_version": 2,
"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"
},
{
"id": "request_changes",
"label": "Request changes"
},
{
"id": "reject",
"label": "Reject"
}
],
"deep_link": "https://superpipeline.dev/b/brd_7c1f/c/crd_6b40"
}

Each of these must fail. The corpus says why:

  • an option id outside GateDecision. Renders a fine button and is refused on resolution — the failure this corpus exists to make loud. (refused by schema)
  • no body. A message with nothing for a stock client to render defeats the reason the marker shape was chosen. (refused by schema)
  • carries tenant_id. Dropped deliberately; its presence means a sender built against the superseded #34 sketch. (refused by schema)
  • carries run_id, task_id and expires_at — all three dropped. Same superseded sketch. (refused by schema)
  • empty options. A decision with nothing to choose is a card that cannot be answered; it must not render as pending. (refused by schema)
  • duplicate option ids. Resolution is by id, so two approve entries are ambiguous regardless of their labels. (refused by unique)
  • a handoff_summary that is not a string. It is displayed text; an object here would be rendered by whatever a host does with a non-string, which is exactly the coercion the renderers refuse. (refused by schema)
  • choice: a v1 card for a variant gate offering approve. Its answer could carry no choice. (refused by recorded)