Skip to content
Registry

kanban

v0.1.15

File-backed kanban board — tickets, threaded comments, agent assignment, the kanban:change and kanban:comment trigger types, and an injectable console board with agent profiles for planning and review.

license: Apache-2.0Used in 1 kitagentsboardconsole-uikanbantickets

Install

bash
iii trigger compose::add worker=kanban@0.1.15

Run in your project with the iii engine running. Exact versions are immutable and digest-pinned.

Agent-ready brief for v0.1.15
Install, config, dependencies, readme, skills and API reference, all in one place. Fetch as agent-context.md for an LLM to consume.
The same content rendered as discrete blocks below is exposed as a single markdown document at /workers/kanban.md?version=0.1.15. Paste it into an LLM prompt or pipe it through curl from a worker.

Install

iii trigger compose::add worker=kanban@0.1.15

Configuration

iii-config.yaml
- agents_path: agents
  columns:
    - id: backlog
      label: Backlog
    - id: todo
      label: To do
    - id: in_progress
      label: In progress
    - id: in_review
      label: In review
    - id: done
      label: Done
  data_path: data/kanban
  default_status: backlog
  id_prefix: KAN
  priorities:
    - low
    - medium
    - high
    - urgent

Dependencies

Dependency · 1Version

Readme

README.md

kanban

A file-backed kanban board for an iii project. Tickets, threaded comments, an activity timeline and agent assignment live in one board.json; every mutation is a kanban::* function, and two trigger types (kanban:change, kanban:comment) let agents wake on what happens to a ticket instead of polling. The worker injects a board page and a ticket screen into the console, and ships five agent profiles — Product Manager, Tech Lead, Backend Engineer, Frontend Engineer, iii ADE Worker Designer — that plan, dispatch, build and review work as tickets on this board.

Table of contents

Install

iii trigger compose::add worker=kanban

iii trigger compose::add declares the worker in worker-compose.yaml and starts it as part of the Compose project. The configuration worker (built into the engine) stores the board settings; iii-directory is optional and supplies the agent profiles the board can assign to.

Quickstart

Create a ticket, claim it, comment, and hand it off. Every ticket has an internal uuid and a human key (KAN-1); both work everywhere a ticket is addressed, case-insensitively.

iii trigger kanban::ticket::create title="Search filters persist" priority=high
iii trigger kanban::ticket::update id=KAN-1 assignee=backend-engineer status=in_progress actor=backend-engineer
iii trigger kanban::comment::create ticket_id=KAN-1 body="Pushed the fix; ready for review." author=backend-engineer
iii trigger kanban::ticket::move id=KAN-1 status=in_review actor=backend-engineer
iii trigger kanban::ticket::get id=kan-1

From a worker, the same calls go through the SDK:

use iii_sdk::protocol::TriggerRequest;
use iii_sdk::{InitOptions, register_worker};
use serde_json::json;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let iii = register_worker("ws://localhost:49134", InitOptions::default());

    let ticket = iii
        .trigger(TriggerRequest {
            function_id: "kanban::ticket::create".into(),
            payload: json!({ "title": "Search filters persist", "priority": "high" }),
            action: None,
            timeout_ms: Some(5_000),
        })
        .await?;
    println!("{}", ticket["key"]); // KAN-1

    let board = iii
        .trigger(TriggerRequest {
            function_id: "kanban::board::get".into(),
            payload: json!({}),
            action: None,
            timeout_ms: Some(5_000),
        })
        .await?;
    println!("{}", board["columns"]);
    Ok(())
}

kanban::ticket::get returns the ticket with its comments and activity inline; kanban::board::get returns every configured column with its ticket summaries (no description or thread). Both list reads take updated_since and compact, and the board takes statuses and a per-column limit, so an agent reads the active lanes in one small call and the done column only for what changed:

iii trigger kanban::board::get --json '{"statuses":["todo","in_progress","in_review"],"compact":true}'
iii trigger kanban::ticket::list --json '{"status":"done","updated_since":"2026-09-10T00:00:00.000Z","compact":true}'

Pass actor on writes and author on comments: the timeline reads honestly, and the comment filters key on exactly that string. Deleting a ticket (kanban::ticket::delete) is a soft delete — the row stays in the board file with deleted_at set and kanban::ticket::restore undoes it — and it is reserved for a person on the console's ticket screen; agents move a finished ticket to in_review or done instead.

The full function list is in skills/SKILL.md; request and response schemas come from engine::functions::info.

Configuration

Settings live in the configuration worker under the id kanban and are edited from the console's Kanban settings form (columns, priorities, prefix, paths) or by writing the YAML file the configuration worker persists. The worker hot-reloads on configuration:updated; no restart is needed.

data_path: data/kanban        # folder holding board.json; relative to III_COMPOSE_DIR (or the process cwd)
id_prefix: KAN                # human keys become KAN-1, KAN-2, …  (^[A-Z][A-Z0-9]*$)
default_status: backlog       # column a new ticket lands in when none is given
columns:                      # left to right; `id` is what tickets store, `label` is what the board shows
  - { id: backlog, label: Backlog }
  - { id: todo, label: To do }
  - { id: in_progress, label: In progress }
  - { id: in_review, label: In review }
  - { id: done, label: Done }
priorities: [low, medium, high, urgent]   # offered on a ticket, lowest first; the first one is the default
agents_path: agents           # fallback folder of <id>.md agent profiles when iii-directory is not installed

A stored value is repaired rather than refused: an unknown default_status falls to the first column, an invalid prefix falls back to KAN, duplicate column ids collapse, and an empty list falls back to the default. Pass --config .yaml to seed the entry on first boot only; afterwards the configuration worker is the source of truth. kanban::config::info prints the resolved absolute paths.

Custom trigger types

Trigger type Config Fires when Payload to subscribers
kanban:change { ticket_id?, events?, ticket?, metadata? } After every mutation. ticket_id (uuid or key) and events narrow it; an empty config fires for everything. { event, ticket_id, ticket_key, ticket, comment, activity, at } — event is one of ticket.created, ticket.updated, ticket.moved, ticket.deleted, ticket.restored, comment.created.
kanban:comment { ticket_id, author?, exclude_author?, root_only?, ticket? } A comment is created on that ticket. ticket_id is required; author keeps one author, exclude_author drops one (your own id), root_only ignores replies. { event: "comment.created", ticket_id, ticket_key, ticket, comment, author, at }

ticket on either type is full (default: the ticket with comments and activity inline) or summary (the board-card fields only); an agent that re-reads the ticket on a wake should pass summary so each wake costs a card, not a thread. kanban:change has no author filter, so a feedback loop that must not wake on its own comments uses kanban:comment with exclude_author:

engine::register_trigger {
  "trigger_type": "kanban:comment",
  "config": { "ticket_id": "KAN-7", "exclude_author": "backend-engineer", "ticket": "summary" },
  "once": false,
  "lifecycle": { "max_fires": 20, "expires_in_ms": 3600000 }
}

Bindings live in the worker's in-process map and die with the process; kanban::config::info reports how many are held under subscribers. Pair a standing wake with a cron check-in over kanban::comment::list, which takes the same filters plus since.

Console pages

While the worker is connected it injects two pages into the console:

  • Kanban (page kanban-board) — the board: one lane per configured column, drag and drop between lanes, a new-ticket dialog, and a lane picker when the pane is narrow. Clicking a card opens the ticket beside the board; the card's Open in this tab action keeps it in the current pane instead (the console reuses any tab that already shows a ticket pane), and the inline view offers Open in its own pane to go the other way.
  • Ticket (page kanban-ticket) — one ticket: status, priority and assignee (from kanban::agent::list), a Markdown description with an editor, and the activity timeline with threaded comments. Delete and restore live here, behind a confirmation.

Both pages stay live over a kanban:change binding, and the Kanban settings form edits the configuration above. Chat renders kanban::* results as ticket cards and kanban:* trigger activity with the ticket and comment it carried. Command palette rows: New ticket, Refresh board, Refresh ticket, Edit description, Write a comment, Back to the board.

Agent profiles

agents/ ships five profiles. Each is a system prompt with preloaded skills and functions; the harness freezes both into every session that runs as that profile, and the board is the only channel between them.

Profile id Role Preloaded skills
product-manager Interviews the user, writes tickets whose descriptions carry observable acceptance criteria, and gates in_review → done (any caveat goes back to in_progress). kanban/tickets/feature-planning, kanban/tickets/acceptance-review, kanban/tickets/kanban-tickets
tech-lead Splits one feature on the seam between backend and frontend, dispatches each ticket with harness::spawn, stays reachable on comment wakes, verifies the seam. kanban/tickets/ticket-orchestration, kanban/tickets/kanban-tickets, kanban/tickets/acceptance-review
backend-engineer Builds workers, functions, triggers and configuration; verifies with a real call; reports on the ticket. kanban/iii-node/index, kanban/iii-node/configuration, kanban/tickets/ticket-worker
frontend-engineer Builds the browser app (Vite, React, TanStack, iii-browser-sdk); verifies in a real browser; reports with screenshots on the ticket. kanban/frontend/iii-browser-sdk, kanban/frontend/react, kanban/frontend/vite, kanban/frontend/tanstack-router, kanban/frontend/tanstack-query, kanban/frontend/web-accessibility, kanban/frontend/web-performance, kanban/frontend/frontend-testing, kanban/tickets/ticket-worker
ade-worker-designer Designs and builds the UI a worker injects into the ADE console — pages, renderers, configuration forms, scoped styles — against @iii-dev/console-ui and the iii Schematic design system; verifies in the running console. kanban/ade-worker-design/index, kanban/ade-worker-design/console-injectable-ui, kanban/ade-worker-design/patterns, kanban/ade-worker-design/console-design, kanban/iii-node/configuration, kanban/tickets/ticket-worker

All four extend the bundled iii-minimal identity and use their profile id as actor / author / exclude_author, so the loop in skills/kanban-tickets.md closes.

Where they land

  • Registry install. iii trigger compose::add worker=kanban publishes the profiles into /.md and the skills under /kanban/…, which is why the skill ids above are prefixed kanban/.
  • Local path:// install. Copy agents/*.md into the project's agents/ folder and skills/** into skills/kanban/ (keeping the same relative layout) so the ids the profiles preload resolve.

directory::agents::list shows them; kanban::agent::list is what the board assigns from.

Picking a model per profile

The profiles ship without a model, so each session takes the model of the send (the console's model picker or harness::send { options: { model } }). To pin one, add model and optionally reasoning_effort to the frontmatter as provider::model. router::models::list prints the catalog for the providers you installed (its ids read provider/model; the profile spells the same key with ::). The examples below use the claude-code provider; with the API-key provider the same models are anthropic::….

---
name: Tech Lead
model: claude-code::claude-fable-5-1
reasoning_effort: high
extends: iii-minimal
---

model inherits through extends, so setting it on a shared base profile pins every child. A useful split, from most to least demanding:

Profile What the work needs Pick
tech-lead Decomposition, contract design, judging a seam that "passes" but does not work; the costliest mistakes happen here. The strongest model you run: claude-code::claude-fable-5-1 (or claude-code::claude-opus-5) with reasoning_effort: high.
product-manager Interviewing, writing precise acceptance criteria, refusing caveats at the gate. Long context, careful language, few calls. claude-code::claude-opus-5 at medium effort; claude-code::claude-sonnet-5 is the economy choice.
backend-engineer Many tool calls, real verification, Rust/Node code. Gains more from a strong coder than from deep deliberation. claude-code::claude-sonnet-5 (or an openai-codex::… model if Codex is your coding provider); raise to Opus for protocol or migration work.
frontend-engineer Same shape as backend plus browser verification and screenshots; visual judgement matters. claude-code::claude-sonnet-5; Opus when the ticket is a design pass.
ade-worker-designer Long design-system and contract skills preloaded (about 40k tokens), visual judgement against screenshots, strict adherence to index.d.ts. claude-code::claude-opus-5; Sonnet for small renderer or form tickets.

Edit the file in agents/ (or directory::agents::update { id, … }) and the next session that runs as that profile picks it up; sessions already running keep the model they started with.

Skills

skills/SKILL.md is the worker overview agents read first. The rest is the working doctrine the profiles preload, one folder per concern (each folder's index.md maps its files):

  • tickets/ — how work moves through the board: kanban-tickets (the shared loop, the comment wake, review vs done, never delete), feature-planning and acceptance-review (the Product Manager's halves), ticket-orchestration and ticket-worker (the dispatcher's and the dispatched engineer's halves).
  • iii-node/ — building a Node worker (package shape, functions, triggers, asset delivery, compose wiring) with its bundled configuration reference.
  • ade-worker-design/ — the designer's half: the injectable UI contract (console-injectable-ui), the iii Schematic design system (console-design) and the record-shaped interaction recipes (patterns).
  • frontend/ — the Frontend Engineer's browser stack: iii-browser-sdk, react, vite, tanstack-router, tanstack-query, web-accessibility, web-performance, frontend-testing.

Fetch any of them with directory::skills::get { "id": "kanban//" }.

Development

# UI (esbuild; react and @iii-dev/console-ui stay external)
pnpm --dir kanban/ui build
# worker
cd kanban
cargo fmt --all -- --check
cargo clippy --locked --all-targets --all-features -- -D warnings
cargo test --locked --all-features

build.rs runs the UI build when ui/dist is missing or stale; set SKIP_UI_BUILD=1 to embed the existing output. For the hot-reload loop run pnpm --dir kanban/ui watch in one terminal and III_KANBAN_UI_WATCH=1 cargo run --bin kanban in another; every open console tab swaps the asset on rebuild. The worker connects to III_URL (default ws://127.0.0.1:49134) and resolves data_path and agents_path against III_COMPOSE_DIR.

Skills

API reference (JSON)

agent-api-reference.json
{
  "functions": [
    {
      "description": "Read a ticket's activity timeline: field changes, lane moves, deletion and comment events, oldest first.",
      "metadata": {},
      "name": "kanban::activity::list",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "limit": {
            "default": null,
            "format": "uint64",
            "minimum": 0,
            "type": [
              "integer",
              "null"
            ]
          },
          "since": {
            "default": null,
            "type": [
              "string",
              "null"
            ]
          },
          "ticket_id": {
            "description": "Ticket uuid or human-readable key (KAN-1, case-insensitive).",
            "type": "string"
          },
          "types": {
            "default": null,
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          }
        },
        "required": [
          "ticket_id"
        ],
        "title": "ActivityListInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "Activity": {
            "properties": {
              "actor": {
                "type": "string"
              },
              "at": {
                "type": "string"
              },
              "changes": {
                "items": {
                  "$ref": "#/definitions/Change"
                },
                "type": [
                  "array",
                  "null"
                ]
              },
              "comment_id": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "id": {
                "type": "string"
              },
              "seq": {
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "ticket_id": {
                "type": "string"
              },
              "type": {
                "description": "ticket.created | ticket.updated | ticket.moved | ticket.deleted | ticket.restored | comment.created",
                "type": "string"
              }
            },
            "required": [
              "actor",
              "at",
              "id",
              "seq",
              "ticket_id",
              "type"
            ],
            "type": "object"
          },
          "Change": {
            "properties": {
              "field": {
                "type": "string"
              },
              "from": true,
              "to": true
            },
            "required": [
              "field",
              "from",
              "to"
            ],
            "type": "object"
          }
        },
        "properties": {
          "activity": {
            "items": {
              "$ref": "#/definitions/Activity"
            },
            "type": "array"
          },
          "count": {
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          }
        },
        "required": [
          "activity",
          "count"
        ],
        "title": "ActivityList",
        "type": "object"
      }
    },
    {
      "description": "List assignable agent profiles, resolved through iii-directory with a fallback to the configured agents folder.",
      "metadata": {},
      "name": "kanban::agent::list",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "title": "Empty",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "AgentProfile": {
            "properties": {
              "color": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "icon": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "id": {
                "description": "Agent profile id used as the ticket assignee.",
                "type": "string"
              },
              "logo": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "model": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "name": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name"
            ],
            "type": "object"
          }
        },
        "properties": {
          "agents": {
            "items": {
              "$ref": "#/definitions/AgentProfile"
            },
            "type": "array"
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "source": {
            "description": "directory | agents-folder | unavailable",
            "type": "string"
          }
        },
        "required": [
          "agents",
          "source"
        ],
        "title": "AgentList",
        "type": "object"
      }
    },
    {
      "description": "Read the board: every configured column with its tickets, plus the resolved paths and priorities. Narrow it with statuses, updated_since and limit, and ask for compact rows to keep the response small.",
      "metadata": {},
      "name": "kanban::board::get",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "compact": {
            "default": false,
            "description": "Return the compact row (key, title, status, priority, assignee, comment_count) instead of the full summary.",
            "type": "boolean"
          },
          "include_deleted": {
            "default": false,
            "description": "Include soft-deleted tickets. Default false.",
            "type": "boolean"
          },
          "limit": {
            "default": null,
            "description": "At most this many tickets per column, from the top of the column.",
            "format": "uint64",
            "minimum": 0,
            "type": [
              "integer",
              "null"
            ]
          },
          "statuses": {
            "default": null,
            "description": "Only these column ids (board order kept). Omit for every column.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "updated_since": {
            "default": null,
            "description": "Only tickets updated after this ISO timestamp — what changed since your last read.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "title": "BoardGetInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "BoardColumnView": {
            "properties": {
              "id": {
                "type": "string"
              },
              "label": {
                "type": "string"
              },
              "tickets": {
                "items": {
                  "$ref": "#/definitions/TicketRow"
                },
                "type": "array"
              }
            },
            "required": [
              "id",
              "label",
              "tickets"
            ],
            "type": "object"
          },
          "TicketBrief": {
            "description": "The compact projection: what an agent needs to recognise a ticket in a list (`compact: true` on `kanban::board::get` / `kanban::ticket::list`). About a third of a summary's size — no uuid, timestamps, labels or order.",
            "properties": {
              "assignee": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "comment_count": {
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "key": {
                "type": "string"
              },
              "priority": {
                "type": "string"
              },
              "status": {
                "type": "string"
              },
              "title": {
                "type": "string"
              }
            },
            "required": [
              "comment_count",
              "key",
              "priority",
              "status",
              "title"
            ],
            "type": "object"
          },
          "TicketRow": {
            "anyOf": [
              {
                "$ref": "#/definitions/TicketSummary"
              },
              {
                "$ref": "#/definitions/TicketBrief"
              }
            ],
            "description": "One list row: the summary by default, the brief when `compact` was asked."
          },
          "TicketSummary": {
            "description": "The board-card projection of a ticket.",
            "properties": {
              "assignee": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "comment_count": {
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "created_at": {
                "type": "string"
              },
              "deleted_at": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "id": {
                "type": "string"
              },
              "key": {
                "type": "string"
              },
              "labels": {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              "order": {
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "priority": {
                "type": "string"
              },
              "status": {
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "updated_at": {
                "type": "string"
              }
            },
            "required": [
              "comment_count",
              "created_at",
              "id",
              "key",
              "labels",
              "order",
              "priority",
              "status",
              "title",
              "updated_at"
            ],
            "type": "object"
          }
        },
        "properties": {
          "board_file": {
            "type": "string"
          },
          "columns": {
            "description": "The columns asked for (all by default), each with the tickets the filters kept.",
            "items": {
              "$ref": "#/definitions/BoardColumnView"
            },
            "type": "array"
          },
          "data_path_resolved": {
            "type": "string"
          },
          "default_status": {
            "type": "string"
          },
          "deleted_count": {
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          },
          "id_prefix": {
            "type": "string"
          },
          "priorities": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "ticket_count": {
            "description": "Every live ticket on the board, regardless of the filters above.",
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          },
          "updated_at": {
            "type": "string"
          }
        },
        "required": [
          "board_file",
          "columns",
          "data_path_resolved",
          "default_status",
          "deleted_count",
          "id_prefix",
          "priorities",
          "ticket_count",
          "updated_at"
        ],
        "title": "BoardView",
        "type": "object"
      }
    },
    {
      "description": "Comment on a ticket, or reply to a comment by passing parent_id. Returns the new comment and the ticket.",
      "metadata": {},
      "name": "kanban::comment::create",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "author": {
            "default": null,
            "description": "Agent profile id, or `user`. Defaults to `user`.",
            "type": [
              "string",
              "null"
            ]
          },
          "body": {
            "description": "Comment body. Markdown is rendered in the console.",
            "type": "string"
          },
          "parent_id": {
            "default": null,
            "description": "Comment id to reply to; replies stay one level deep.",
            "type": [
              "string",
              "null"
            ]
          },
          "ticket_id": {
            "description": "Ticket uuid or human-readable key (KAN-1, case-insensitive).",
            "type": "string"
          }
        },
        "required": [
          "body",
          "ticket_id"
        ],
        "title": "CommentCreateInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "Activity": {
            "properties": {
              "actor": {
                "type": "string"
              },
              "at": {
                "type": "string"
              },
              "changes": {
                "items": {
                  "$ref": "#/definitions/Change"
                },
                "type": [
                  "array",
                  "null"
                ]
              },
              "comment_id": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "id": {
                "type": "string"
              },
              "seq": {
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "ticket_id": {
                "type": "string"
              },
              "type": {
                "description": "ticket.created | ticket.updated | ticket.moved | ticket.deleted | ticket.restored | comment.created",
                "type": "string"
              }
            },
            "required": [
              "actor",
              "at",
              "id",
              "seq",
              "ticket_id",
              "type"
            ],
            "type": "object"
          },
          "Change": {
            "properties": {
              "field": {
                "type": "string"
              },
              "from": true,
              "to": true
            },
            "required": [
              "field",
              "from",
              "to"
            ],
            "type": "object"
          },
          "Comment": {
            "properties": {
              "author": {
                "description": "Agent profile id, or `user`.",
                "type": "string"
              },
              "body": {
                "type": "string"
              },
              "created_at": {
                "type": "string"
              },
              "id": {
                "type": "string"
              },
              "parent_id": {
                "default": null,
                "description": "Set for a reply; replies stay one level deep.",
                "type": [
                  "string",
                  "null"
                ]
              },
              "ticket_id": {
                "type": "string"
              }
            },
            "required": [
              "author",
              "body",
              "created_at",
              "id",
              "ticket_id"
            ],
            "type": "object"
          },
          "Ticket": {
            "properties": {
              "activity": {
                "default": [],
                "items": {
                  "$ref": "#/definitions/Activity"
                },
                "type": "array"
              },
              "assignee": {
                "default": null,
                "description": "Agent profile id.",
                "type": [
                  "string",
                  "null"
                ]
              },
              "comments": {
                "default": [],
                "items": {
                  "$ref": "#/definitions/Comment"
                },
                "type": "array"
              },
              "created_at": {
                "type": "string"
              },
              "created_by": {
                "default": "user",
                "type": "string"
              },
              "deleted_at": {
                "default": null,
                "description": "Set when soft-deleted; the row stays on disk.",
                "type": [
                  "string",
                  "null"
                ]
              },
              "description": {
                "default": "",
                "type": "string"
              },
              "id": {
                "description": "Internal uuid.",
                "type": "string"
              },
              "key": {
                "description": "Human-readable id, e.g. KAN-1.",
                "type": "string"
              },
              "labels": {
                "default": [],
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              "order": {
                "default": 0,
                "description": "Position inside its column.",
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "priority": {
                "type": "string"
              },
              "status": {
                "description": "Column id.",
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "updated_at": {
                "type": "string"
              }
            },
            "required": [
              "created_at",
              "id",
              "key",
              "priority",
              "status",
              "title",
              "updated_at"
            ],
            "type": "object"
          }
        },
        "properties": {
          "comment": {
            "$ref": "#/definitions/Comment"
          },
          "ticket": {
            "$ref": "#/definitions/Ticket"
          }
        },
        "required": [
          "comment",
          "ticket"
        ],
        "title": "CommentCreated",
        "type": "object"
      }
    },
    {
      "description": "Read a ticket's comments with filtering, mirroring the kanban:comment trigger: by author, excluding an author, roots only, or after a timestamp.",
      "metadata": {},
      "name": "kanban::comment::list",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "author": {
            "default": null,
            "description": "Only comments by exactly this author.",
            "type": [
              "string",
              "null"
            ]
          },
          "exclude_author": {
            "default": null,
            "description": "Skip comments by this author — e.g. your own.",
            "type": [
              "string",
              "null"
            ]
          },
          "include_deleted": {
            "default": false,
            "type": "boolean"
          },
          "limit": {
            "default": null,
            "format": "uint64",
            "minimum": 0,
            "type": [
              "integer",
              "null"
            ]
          },
          "parent_id": {
            "default": null,
            "type": [
              "string",
              "null"
            ]
          },
          "root_only": {
            "default": false,
            "type": "boolean"
          },
          "since": {
            "default": null,
            "description": "ISO timestamp; only comments created after it.",
            "type": [
              "string",
              "null"
            ]
          },
          "ticket_id": {
            "description": "Ticket uuid or human-readable key (KAN-1, case-insensitive).",
            "type": "string"
          }
        },
        "required": [
          "ticket_id"
        ],
        "title": "CommentListInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "Comment": {
            "properties": {
              "author": {
                "description": "Agent profile id, or `user`.",
                "type": "string"
              },
              "body": {
                "type": "string"
              },
              "created_at": {
                "type": "string"
              },
              "id": {
                "type": "string"
              },
              "parent_id": {
                "default": null,
                "description": "Set for a reply; replies stay one level deep.",
                "type": [
                  "string",
                  "null"
                ]
              },
              "ticket_id": {
                "type": "string"
              }
            },
            "required": [
              "author",
              "body",
              "created_at",
              "id",
              "ticket_id"
            ],
            "type": "object"
          }
        },
        "properties": {
          "comments": {
            "items": {
              "$ref": "#/definitions/Comment"
            },
            "type": "array"
          },
          "count": {
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          }
        },
        "required": [
          "comments",
          "count"
        ],
        "title": "CommentList",
        "type": "object"
      }
    },
    {
      "description": "Resolved kanban settings: the folder the board file lives in, the columns, and the numbering prefix.",
      "metadata": {},
      "name": "kanban::config::info",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "title": "Empty",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "Column": {
            "properties": {
              "id": {
                "description": "Stable column id stored on tickets.",
                "type": "string"
              },
              "label": {
                "description": "Name shown on the board.",
                "type": "string"
              }
            },
            "required": [
              "id",
              "label"
            ],
            "type": "object"
          },
          "SubscriberCounts": {
            "properties": {
              "change": {
                "format": "uint",
                "minimum": 0,
                "type": "integer"
              },
              "comment": {
                "format": "uint",
                "minimum": 0,
                "type": "integer"
              }
            },
            "required": [
              "change",
              "comment"
            ],
            "type": "object"
          }
        },
        "properties": {
          "agents_path": {
            "type": "string"
          },
          "agents_path_resolved": {
            "type": "string"
          },
          "board_file": {
            "description": "Absolute path of board.json.",
            "type": "string"
          },
          "columns": {
            "description": "Board columns left to right.",
            "items": {
              "$ref": "#/definitions/Column"
            },
            "type": "array"
          },
          "configuration_id": {
            "type": "string"
          },
          "data_path": {
            "description": "Configured path, as written.",
            "type": "string"
          },
          "data_path_resolved": {
            "description": "Absolute folder the board file is read from.",
            "type": "string"
          },
          "default_status": {
            "type": "string"
          },
          "id_prefix": {
            "type": "string"
          },
          "priorities": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "project_root": {
            "type": "string"
          },
          "subscribers": {
            "$ref": "#/definitions/SubscriberCounts"
          }
        },
        "required": [
          "agents_path",
          "agents_path_resolved",
          "board_file",
          "columns",
          "configuration_id",
          "data_path",
          "data_path_resolved",
          "default_status",
          "id_prefix",
          "priorities",
          "project_root",
          "subscribers"
        ],
        "title": "ConfigInfo",
        "type": "object"
      }
    },
    {
      "description": "Internal: re-read the kanban configuration after an operator change.",
      "metadata": {
        "internal": true
      },
      "name": "kanban::on-config-change",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "description": "Trigger payload for `<worker>::on-config-change`. Advisory only: handlers re-fetch the authoritative value and ignore it, so a direct call can never inject config.",
        "properties": {
          "id": {
            "default": null,
            "description": "Configuration id that changed.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "title": "OnConfigChangeEvent",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "description": "Ack returned by the internal `<worker>::on-config-change` handler.",
        "properties": {
          "ok": {
            "type": "boolean"
          }
        },
        "required": [
          "ok"
        ],
        "title": "OnConfigChangeResponse",
        "type": "object"
      }
    },
    {
      "description": "Create a ticket on the board and return it.",
      "metadata": {},
      "name": "kanban::ticket::create",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "actor": {
            "default": null,
            "description": "Who is making the change. Defaults to `user`.",
            "type": [
              "string",
              "null"
            ]
          },
          "assignee": {
            "default": null,
            "description": "Agent profile id.",
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "default": null,
            "type": [
              "string",
              "null"
            ]
          },
          "labels": {
            "default": null,
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "priority": {
            "default": null,
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "default": null,
            "description": "Column id; defaults to the configured default_status.",
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "description": "Required.",
            "type": "string"
          }
        },
        "required": [
          "title"
        ],
        "title": "TicketCreateInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "Activity": {
            "properties": {
              "actor": {
                "type": "string"
              },
              "at": {
                "type": "string"
              },
              "changes": {
                "items": {
                  "$ref": "#/definitions/Change"
                },
                "type": [
                  "array",
                  "null"
                ]
              },
              "comment_id": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "id": {
                "type": "string"
              },
              "seq": {
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "ticket_id": {
                "type": "string"
              },
              "type": {
                "description": "ticket.created | ticket.updated | ticket.moved | ticket.deleted | ticket.restored | comment.created",
                "type": "string"
              }
            },
            "required": [
              "actor",
              "at",
              "id",
              "seq",
              "ticket_id",
              "type"
            ],
            "type": "object"
          },
          "Change": {
            "properties": {
              "field": {
                "type": "string"
              },
              "from": true,
              "to": true
            },
            "required": [
              "field",
              "from",
              "to"
            ],
            "type": "object"
          },
          "Comment": {
            "properties": {
              "author": {
                "description": "Agent profile id, or `user`.",
                "type": "string"
              },
              "body": {
                "type": "string"
              },
              "created_at": {
                "type": "string"
              },
              "id": {
                "type": "string"
              },
              "parent_id": {
                "default": null,
                "description": "Set for a reply; replies stay one level deep.",
                "type": [
                  "string",
                  "null"
                ]
              },
              "ticket_id": {
                "type": "string"
              }
            },
            "required": [
              "author",
              "body",
              "created_at",
              "id",
              "ticket_id"
            ],
            "type": "object"
          }
        },
        "properties": {
          "activity": {
            "default": [],
            "items": {
              "$ref": "#/definitions/Activity"
            },
            "type": "array"
          },
          "assignee": {
            "default": null,
            "description": "Agent profile id.",
            "type": [
              "string",
              "null"
            ]
          },
          "comments": {
            "default": [],
            "items": {
              "$ref": "#/definitions/Comment"
            },
            "type": "array"
          },
          "created_at": {
            "type": "string"
          },
          "created_by": {
            "default": "user",
            "type": "string"
          },
          "deleted_at": {
            "default": null,
            "description": "Set when soft-deleted; the row stays on disk.",
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "default": "",
            "type": "string"
          },
          "id": {
            "description": "Internal uuid.",
            "type": "string"
          },
          "key": {
            "description": "Human-readable id, e.g. KAN-1.",
            "type": "string"
          },
          "labels": {
            "default": [],
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "order": {
            "default": 0,
            "description": "Position inside its column.",
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          },
          "priority": {
            "type": "string"
          },
          "status": {
            "description": "Column id.",
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        },
        "required": [
          "created_at",
          "id",
          "key",
          "priority",
          "status",
          "title",
          "updated_at"
        ],
        "title": "Ticket",
        "type": "object"
      }
    },
    {
      "description": "Soft-delete a ticket: it leaves the board but stays in the board file.",
      "metadata": {},
      "name": "kanban::ticket::delete",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "actor": {
            "default": null,
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Ticket uuid or human-readable key (KAN-1, case-insensitive).",
            "type": "string"
          }
        },
        "required": [
          "id"
        ],
        "title": "TicketRefInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "Activity": {
            "properties": {
              "actor": {
                "type": "string"
              },
              "at": {
                "type": "string"
              },
              "changes": {
                "items": {
                  "$ref": "#/definitions/Change"
                },
                "type": [
                  "array",
                  "null"
                ]
              },
              "comment_id": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "id": {
                "type": "string"
              },
              "seq": {
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "ticket_id": {
                "type": "string"
              },
              "type": {
                "description": "ticket.created | ticket.updated | ticket.moved | ticket.deleted | ticket.restored | comment.created",
                "type": "string"
              }
            },
            "required": [
              "actor",
              "at",
              "id",
              "seq",
              "ticket_id",
              "type"
            ],
            "type": "object"
          },
          "Change": {
            "properties": {
              "field": {
                "type": "string"
              },
              "from": true,
              "to": true
            },
            "required": [
              "field",
              "from",
              "to"
            ],
            "type": "object"
          },
          "Comment": {
            "properties": {
              "author": {
                "description": "Agent profile id, or `user`.",
                "type": "string"
              },
              "body": {
                "type": "string"
              },
              "created_at": {
                "type": "string"
              },
              "id": {
                "type": "string"
              },
              "parent_id": {
                "default": null,
                "description": "Set for a reply; replies stay one level deep.",
                "type": [
                  "string",
                  "null"
                ]
              },
              "ticket_id": {
                "type": "string"
              }
            },
            "required": [
              "author",
              "body",
              "created_at",
              "id",
              "ticket_id"
            ],
            "type": "object"
          }
        },
        "properties": {
          "activity": {
            "default": [],
            "items": {
              "$ref": "#/definitions/Activity"
            },
            "type": "array"
          },
          "assignee": {
            "default": null,
            "description": "Agent profile id.",
            "type": [
              "string",
              "null"
            ]
          },
          "comments": {
            "default": [],
            "items": {
              "$ref": "#/definitions/Comment"
            },
            "type": "array"
          },
          "created_at": {
            "type": "string"
          },
          "created_by": {
            "default": "user",
            "type": "string"
          },
          "deleted_at": {
            "default": null,
            "description": "Set when soft-deleted; the row stays on disk.",
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "default": "",
            "type": "string"
          },
          "id": {
            "description": "Internal uuid.",
            "type": "string"
          },
          "key": {
            "description": "Human-readable id, e.g. KAN-1.",
            "type": "string"
          },
          "labels": {
            "default": [],
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "order": {
            "default": 0,
            "description": "Position inside its column.",
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          },
          "priority": {
            "type": "string"
          },
          "status": {
            "description": "Column id.",
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        },
        "required": [
          "created_at",
          "id",
          "key",
          "priority",
          "status",
          "title",
          "updated_at"
        ],
        "title": "Ticket",
        "type": "object"
      }
    },
    {
      "description": "Read one ticket with its comments and activity. The id accepts the internal uuid or the human-readable key.",
      "metadata": {},
      "name": "kanban::ticket::get",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "id": {
            "description": "Ticket uuid or human-readable key (KAN-1, case-insensitive).",
            "type": "string"
          }
        },
        "required": [
          "id"
        ],
        "title": "TicketGetInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "Activity": {
            "properties": {
              "actor": {
                "type": "string"
              },
              "at": {
                "type": "string"
              },
              "changes": {
                "items": {
                  "$ref": "#/definitions/Change"
                },
                "type": [
                  "array",
                  "null"
                ]
              },
              "comment_id": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "id": {
                "type": "string"
              },
              "seq": {
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "ticket_id": {
                "type": "string"
              },
              "type": {
                "description": "ticket.created | ticket.updated | ticket.moved | ticket.deleted | ticket.restored | comment.created",
                "type": "string"
              }
            },
            "required": [
              "actor",
              "at",
              "id",
              "seq",
              "ticket_id",
              "type"
            ],
            "type": "object"
          },
          "Change": {
            "properties": {
              "field": {
                "type": "string"
              },
              "from": true,
              "to": true
            },
            "required": [
              "field",
              "from",
              "to"
            ],
            "type": "object"
          },
          "Comment": {
            "properties": {
              "author": {
                "description": "Agent profile id, or `user`.",
                "type": "string"
              },
              "body": {
                "type": "string"
              },
              "created_at": {
                "type": "string"
              },
              "id": {
                "type": "string"
              },
              "parent_id": {
                "default": null,
                "description": "Set for a reply; replies stay one level deep.",
                "type": [
                  "string",
                  "null"
                ]
              },
              "ticket_id": {
                "type": "string"
              }
            },
            "required": [
              "author",
              "body",
              "created_at",
              "id",
              "ticket_id"
            ],
            "type": "object"
          }
        },
        "properties": {
          "activity": {
            "default": [],
            "items": {
              "$ref": "#/definitions/Activity"
            },
            "type": "array"
          },
          "assignee": {
            "default": null,
            "description": "Agent profile id.",
            "type": [
              "string",
              "null"
            ]
          },
          "comments": {
            "default": [],
            "items": {
              "$ref": "#/definitions/Comment"
            },
            "type": "array"
          },
          "created_at": {
            "type": "string"
          },
          "created_by": {
            "default": "user",
            "type": "string"
          },
          "deleted_at": {
            "default": null,
            "description": "Set when soft-deleted; the row stays on disk.",
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "default": "",
            "type": "string"
          },
          "id": {
            "description": "Internal uuid.",
            "type": "string"
          },
          "key": {
            "description": "Human-readable id, e.g. KAN-1.",
            "type": "string"
          },
          "labels": {
            "default": [],
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "order": {
            "default": 0,
            "description": "Position inside its column.",
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          },
          "priority": {
            "type": "string"
          },
          "status": {
            "description": "Column id.",
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        },
        "required": [
          "created_at",
          "id",
          "key",
          "priority",
          "status",
          "title",
          "updated_at"
        ],
        "title": "Ticket",
        "type": "object"
      }
    },
    {
      "description": "List tickets, optionally narrowed to a column, an assignee or an updated_since timestamp; compact rows carry only key, title, status, priority, assignee and comment_count.",
      "metadata": {},
      "name": "kanban::ticket::list",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "assignee": {
            "default": null,
            "description": "Agent profile id; empty string matches unassigned.",
            "type": [
              "string",
              "null"
            ]
          },
          "compact": {
            "default": false,
            "description": "Return the compact row (key, title, status, priority, assignee, comment_count) instead of the full summary.",
            "type": "boolean"
          },
          "include_deleted": {
            "default": false,
            "type": "boolean"
          },
          "limit": {
            "default": null,
            "format": "uint64",
            "minimum": 0,
            "type": [
              "integer",
              "null"
            ]
          },
          "status": {
            "default": null,
            "description": "Column id.",
            "type": [
              "string",
              "null"
            ]
          },
          "updated_since": {
            "default": null,
            "description": "Only tickets updated after this ISO timestamp.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "title": "TicketListInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "TicketBrief": {
            "description": "The compact projection: what an agent needs to recognise a ticket in a list (`compact: true` on `kanban::board::get` / `kanban::ticket::list`). About a third of a summary's size — no uuid, timestamps, labels or order.",
            "properties": {
              "assignee": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "comment_count": {
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "key": {
                "type": "string"
              },
              "priority": {
                "type": "string"
              },
              "status": {
                "type": "string"
              },
              "title": {
                "type": "string"
              }
            },
            "required": [
              "comment_count",
              "key",
              "priority",
              "status",
              "title"
            ],
            "type": "object"
          },
          "TicketRow": {
            "anyOf": [
              {
                "$ref": "#/definitions/TicketSummary"
              },
              {
                "$ref": "#/definitions/TicketBrief"
              }
            ],
            "description": "One list row: the summary by default, the brief when `compact` was asked."
          },
          "TicketSummary": {
            "description": "The board-card projection of a ticket.",
            "properties": {
              "assignee": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "comment_count": {
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "created_at": {
                "type": "string"
              },
              "deleted_at": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "id": {
                "type": "string"
              },
              "key": {
                "type": "string"
              },
              "labels": {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              "order": {
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "priority": {
                "type": "string"
              },
              "status": {
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "updated_at": {
                "type": "string"
              }
            },
            "required": [
              "comment_count",
              "created_at",
              "id",
              "key",
              "labels",
              "order",
              "priority",
              "status",
              "title",
              "updated_at"
            ],
            "type": "object"
          }
        },
        "properties": {
          "count": {
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          },
          "tickets": {
            "items": {
              "$ref": "#/definitions/TicketRow"
            },
            "type": "array"
          }
        },
        "required": [
          "count",
          "tickets"
        ],
        "title": "TicketList",
        "type": "object"
      }
    },
    {
      "description": "Move a ticket to a column (and position inside it); used by the board drag and drop.",
      "metadata": {},
      "name": "kanban::ticket::move",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "actor": {
            "default": null,
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Ticket uuid or human-readable key (KAN-1, case-insensitive).",
            "type": "string"
          },
          "index": {
            "default": null,
            "description": "Zero-based position in the target column.",
            "format": "uint64",
            "minimum": 0,
            "type": [
              "integer",
              "null"
            ]
          },
          "status": {
            "description": "Target column id.",
            "type": "string"
          }
        },
        "required": [
          "id",
          "status"
        ],
        "title": "TicketMoveInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "Activity": {
            "properties": {
              "actor": {
                "type": "string"
              },
              "at": {
                "type": "string"
              },
              "changes": {
                "items": {
                  "$ref": "#/definitions/Change"
                },
                "type": [
                  "array",
                  "null"
                ]
              },
              "comment_id": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "id": {
                "type": "string"
              },
              "seq": {
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "ticket_id": {
                "type": "string"
              },
              "type": {
                "description": "ticket.created | ticket.updated | ticket.moved | ticket.deleted | ticket.restored | comment.created",
                "type": "string"
              }
            },
            "required": [
              "actor",
              "at",
              "id",
              "seq",
              "ticket_id",
              "type"
            ],
            "type": "object"
          },
          "Change": {
            "properties": {
              "field": {
                "type": "string"
              },
              "from": true,
              "to": true
            },
            "required": [
              "field",
              "from",
              "to"
            ],
            "type": "object"
          },
          "Comment": {
            "properties": {
              "author": {
                "description": "Agent profile id, or `user`.",
                "type": "string"
              },
              "body": {
                "type": "string"
              },
              "created_at": {
                "type": "string"
              },
              "id": {
                "type": "string"
              },
              "parent_id": {
                "default": null,
                "description": "Set for a reply; replies stay one level deep.",
                "type": [
                  "string",
                  "null"
                ]
              },
              "ticket_id": {
                "type": "string"
              }
            },
            "required": [
              "author",
              "body",
              "created_at",
              "id",
              "ticket_id"
            ],
            "type": "object"
          }
        },
        "properties": {
          "activity": {
            "default": [],
            "items": {
              "$ref": "#/definitions/Activity"
            },
            "type": "array"
          },
          "assignee": {
            "default": null,
            "description": "Agent profile id.",
            "type": [
              "string",
              "null"
            ]
          },
          "comments": {
            "default": [],
            "items": {
              "$ref": "#/definitions/Comment"
            },
            "type": "array"
          },
          "created_at": {
            "type": "string"
          },
          "created_by": {
            "default": "user",
            "type": "string"
          },
          "deleted_at": {
            "default": null,
            "description": "Set when soft-deleted; the row stays on disk.",
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "default": "",
            "type": "string"
          },
          "id": {
            "description": "Internal uuid.",
            "type": "string"
          },
          "key": {
            "description": "Human-readable id, e.g. KAN-1.",
            "type": "string"
          },
          "labels": {
            "default": [],
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "order": {
            "default": 0,
            "description": "Position inside its column.",
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          },
          "priority": {
            "type": "string"
          },
          "status": {
            "description": "Column id.",
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        },
        "required": [
          "created_at",
          "id",
          "key",
          "priority",
          "status",
          "title",
          "updated_at"
        ],
        "title": "Ticket",
        "type": "object"
      }
    },
    {
      "description": "Put a soft-deleted ticket back on the board.",
      "metadata": {},
      "name": "kanban::ticket::restore",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "actor": {
            "default": null,
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Ticket uuid or human-readable key (KAN-1, case-insensitive).",
            "type": "string"
          }
        },
        "required": [
          "id"
        ],
        "title": "TicketRefInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "Activity": {
            "properties": {
              "actor": {
                "type": "string"
              },
              "at": {
                "type": "string"
              },
              "changes": {
                "items": {
                  "$ref": "#/definitions/Change"
                },
                "type": [
                  "array",
                  "null"
                ]
              },
              "comment_id": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "id": {
                "type": "string"
              },
              "seq": {
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "ticket_id": {
                "type": "string"
              },
              "type": {
                "description": "ticket.created | ticket.updated | ticket.moved | ticket.deleted | ticket.restored | comment.created",
                "type": "string"
              }
            },
            "required": [
              "actor",
              "at",
              "id",
              "seq",
              "ticket_id",
              "type"
            ],
            "type": "object"
          },
          "Change": {
            "properties": {
              "field": {
                "type": "string"
              },
              "from": true,
              "to": true
            },
            "required": [
              "field",
              "from",
              "to"
            ],
            "type": "object"
          },
          "Comment": {
            "properties": {
              "author": {
                "description": "Agent profile id, or `user`.",
                "type": "string"
              },
              "body": {
                "type": "string"
              },
              "created_at": {
                "type": "string"
              },
              "id": {
                "type": "string"
              },
              "parent_id": {
                "default": null,
                "description": "Set for a reply; replies stay one level deep.",
                "type": [
                  "string",
                  "null"
                ]
              },
              "ticket_id": {
                "type": "string"
              }
            },
            "required": [
              "author",
              "body",
              "created_at",
              "id",
              "ticket_id"
            ],
            "type": "object"
          }
        },
        "properties": {
          "activity": {
            "default": [],
            "items": {
              "$ref": "#/definitions/Activity"
            },
            "type": "array"
          },
          "assignee": {
            "default": null,
            "description": "Agent profile id.",
            "type": [
              "string",
              "null"
            ]
          },
          "comments": {
            "default": [],
            "items": {
              "$ref": "#/definitions/Comment"
            },
            "type": "array"
          },
          "created_at": {
            "type": "string"
          },
          "created_by": {
            "default": "user",
            "type": "string"
          },
          "deleted_at": {
            "default": null,
            "description": "Set when soft-deleted; the row stays on disk.",
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "default": "",
            "type": "string"
          },
          "id": {
            "description": "Internal uuid.",
            "type": "string"
          },
          "key": {
            "description": "Human-readable id, e.g. KAN-1.",
            "type": "string"
          },
          "labels": {
            "default": [],
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "order": {
            "default": 0,
            "description": "Position inside its column.",
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          },
          "priority": {
            "type": "string"
          },
          "status": {
            "description": "Column id.",
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        },
        "required": [
          "created_at",
          "id",
          "key",
          "priority",
          "status",
          "title",
          "updated_at"
        ],
        "title": "Ticket",
        "type": "object"
      }
    },
    {
      "description": "Update a ticket field (title, description, status, priority, assignee, labels) and return the ticket.",
      "metadata": {},
      "name": "kanban::ticket::update",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "actor": {
            "default": null,
            "type": [
              "string",
              "null"
            ]
          },
          "assignee": {
            "default": null,
            "description": "Agent profile id, or null to unassign.",
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "default": null,
            "type": [
              "string",
              "null"
            ]
          },
          "id": {
            "description": "Ticket uuid or human-readable key (KAN-1, case-insensitive).",
            "type": "string"
          },
          "labels": {
            "default": null,
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "priority": {
            "default": null,
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "default": null,
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "default": null,
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id"
        ],
        "title": "TicketUpdateInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "Activity": {
            "properties": {
              "actor": {
                "type": "string"
              },
              "at": {
                "type": "string"
              },
              "changes": {
                "items": {
                  "$ref": "#/definitions/Change"
                },
                "type": [
                  "array",
                  "null"
                ]
              },
              "comment_id": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "id": {
                "type": "string"
              },
              "seq": {
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "ticket_id": {
                "type": "string"
              },
              "type": {
                "description": "ticket.created | ticket.updated | ticket.moved | ticket.deleted | ticket.restored | comment.created",
                "type": "string"
              }
            },
            "required": [
              "actor",
              "at",
              "id",
              "seq",
              "ticket_id",
              "type"
            ],
            "type": "object"
          },
          "Change": {
            "properties": {
              "field": {
                "type": "string"
              },
              "from": true,
              "to": true
            },
            "required": [
              "field",
              "from",
              "to"
            ],
            "type": "object"
          },
          "Comment": {
            "properties": {
              "author": {
                "description": "Agent profile id, or `user`.",
                "type": "string"
              },
              "body": {
                "type": "string"
              },
              "created_at": {
                "type": "string"
              },
              "id": {
                "type": "string"
              },
              "parent_id": {
                "default": null,
                "description": "Set for a reply; replies stay one level deep.",
                "type": [
                  "string",
                  "null"
                ]
              },
              "ticket_id": {
                "type": "string"
              }
            },
            "required": [
              "author",
              "body",
              "created_at",
              "id",
              "ticket_id"
            ],
            "type": "object"
          }
        },
        "properties": {
          "activity": {
            "default": [],
            "items": {
              "$ref": "#/definitions/Activity"
            },
            "type": "array"
          },
          "assignee": {
            "default": null,
            "description": "Agent profile id.",
            "type": [
              "string",
              "null"
            ]
          },
          "comments": {
            "default": [],
            "items": {
              "$ref": "#/definitions/Comment"
            },
            "type": "array"
          },
          "created_at": {
            "type": "string"
          },
          "created_by": {
            "default": "user",
            "type": "string"
          },
          "deleted_at": {
            "default": null,
            "description": "Set when soft-deleted; the row stays on disk.",
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "default": "",
            "type": "string"
          },
          "id": {
            "description": "Internal uuid.",
            "type": "string"
          },
          "key": {
            "description": "Human-readable id, e.g. KAN-1.",
            "type": "string"
          },
          "labels": {
            "default": [],
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "order": {
            "default": 0,
            "description": "Position inside its column.",
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          },
          "priority": {
            "type": "string"
          },
          "status": {
            "description": "Column id.",
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "updated_at": {
            "type": "string"
          }
        },
        "required": [
          "created_at",
          "id",
          "key",
          "priority",
          "status",
          "title",
          "updated_at"
        ],
        "title": "Ticket",
        "type": "object"
      }
    },
    {
      "description": "Serve the kanban worker's injected console UI assets (content function for its console:script / console:style triggers).",
      "metadata": {
        "internal": true
      },
      "name": "kanban::ui-content",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "description": "Input of the content function: the console asks for one asset by path.",
        "properties": {
          "path": {
            "description": "The asset path from the trigger config (e.g. `state/page.js`).",
            "type": "string"
          }
        },
        "required": [
          "path"
        ],
        "title": "UiContentInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "description": "Output of the content function.",
        "properties": {
          "content": {
            "description": "The asset source, verbatim.",
            "type": "string"
          },
          "content_type": {
            "description": "MIME type the console should serve the asset with.",
            "type": "string"
          }
        },
        "required": [
          "content",
          "content_type"
        ],
        "title": "UiContentResult",
        "type": "object"
      }
    }
  ],
  "triggers": [
    {
      "description": "Fires after every kanban mutation with the whole ticket. Config: { ticket_id?, events?, metadata? } — ticket_id matches the uuid or the human key.",
      "invocation_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "TicketDetail": {
            "description": "How much of the ticket a delivery carries. `full` is the ticket with its comments and activity inline; `summary` is the board-card projection (key, title, status, priority, assignee, labels, order, timestamps, comment_count) — the right choice for an agent that re-reads the ticket with `kanban::ticket::get` anyway.",
            "enum": [
              "full",
              "summary"
            ],
            "type": "string"
          }
        },
        "properties": {
          "events": {
            "description": "Event names to fire for (ticket.created, ticket.updated, ticket.moved, ticket.deleted, ticket.restored, comment.created). Omit for all.",
            "items": {
              "type": "string"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "metadata": {
            "description": "Metadata attached to every invocation this binding receives."
          },
          "ticket": {
            "anyOf": [
              {
                "$ref": "#/definitions/TicketDetail"
              },
              {
                "type": "null"
              }
            ],
            "description": "`full` (default) delivers the whole ticket; `summary` only its board-card fields."
          },
          "ticket_id": {
            "description": "Ticket uuid or human key. Omit to fire for every ticket.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "title": "ChangeConfig",
        "type": "object"
      },
      "metadata": {},
      "name": "kanban:change",
      "return_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "Activity": {
            "properties": {
              "actor": {
                "type": "string"
              },
              "at": {
                "type": "string"
              },
              "changes": {
                "items": {
                  "$ref": "#/definitions/Change"
                },
                "type": [
                  "array",
                  "null"
                ]
              },
              "comment_id": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "id": {
                "type": "string"
              },
              "seq": {
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "ticket_id": {
                "type": "string"
              },
              "type": {
                "description": "ticket.created | ticket.updated | ticket.moved | ticket.deleted | ticket.restored | comment.created",
                "type": "string"
              }
            },
            "required": [
              "actor",
              "at",
              "id",
              "seq",
              "ticket_id",
              "type"
            ],
            "type": "object"
          },
          "Change": {
            "properties": {
              "field": {
                "type": "string"
              },
              "from": true,
              "to": true
            },
            "required": [
              "field",
              "from",
              "to"
            ],
            "type": "object"
          },
          "Comment": {
            "properties": {
              "author": {
                "description": "Agent profile id, or `user`.",
                "type": "string"
              },
              "body": {
                "type": "string"
              },
              "created_at": {
                "type": "string"
              },
              "id": {
                "type": "string"
              },
              "parent_id": {
                "default": null,
                "description": "Set for a reply; replies stay one level deep.",
                "type": [
                  "string",
                  "null"
                ]
              },
              "ticket_id": {
                "type": "string"
              }
            },
            "required": [
              "author",
              "body",
              "created_at",
              "id",
              "ticket_id"
            ],
            "type": "object"
          },
          "Ticket": {
            "properties": {
              "activity": {
                "default": [],
                "items": {
                  "$ref": "#/definitions/Activity"
                },
                "type": "array"
              },
              "assignee": {
                "default": null,
                "description": "Agent profile id.",
                "type": [
                  "string",
                  "null"
                ]
              },
              "comments": {
                "default": [],
                "items": {
                  "$ref": "#/definitions/Comment"
                },
                "type": "array"
              },
              "created_at": {
                "type": "string"
              },
              "created_by": {
                "default": "user",
                "type": "string"
              },
              "deleted_at": {
                "default": null,
                "description": "Set when soft-deleted; the row stays on disk.",
                "type": [
                  "string",
                  "null"
                ]
              },
              "description": {
                "default": "",
                "type": "string"
              },
              "id": {
                "description": "Internal uuid.",
                "type": "string"
              },
              "key": {
                "description": "Human-readable id, e.g. KAN-1.",
                "type": "string"
              },
              "labels": {
                "default": [],
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              "order": {
                "default": 0,
                "description": "Position inside its column.",
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "priority": {
                "type": "string"
              },
              "status": {
                "description": "Column id.",
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "updated_at": {
                "type": "string"
              }
            },
            "required": [
              "created_at",
              "id",
              "key",
              "priority",
              "status",
              "title",
              "updated_at"
            ],
            "type": "object"
          },
          "TicketPayload": {
            "anyOf": [
              {
                "$ref": "#/definitions/Ticket"
              },
              {
                "$ref": "#/definitions/TicketSummary"
              }
            ],
            "description": "The `ticket` field of a delivery: the whole ticket, or its summary when the binding asked for `ticket: summary`."
          },
          "TicketSummary": {
            "description": "The board-card projection of a ticket.",
            "properties": {
              "assignee": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "comment_count": {
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "created_at": {
                "type": "string"
              },
              "deleted_at": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "id": {
                "type": "string"
              },
              "key": {
                "type": "string"
              },
              "labels": {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              "order": {
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "priority": {
                "type": "string"
              },
              "status": {
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "updated_at": {
                "type": "string"
              }
            },
            "required": [
              "comment_count",
              "created_at",
              "id",
              "key",
              "labels",
              "order",
              "priority",
              "status",
              "title",
              "updated_at"
            ],
            "type": "object"
          }
        },
        "properties": {
          "activity": {
            "anyOf": [
              {
                "$ref": "#/definitions/Activity"
              },
              {
                "type": "null"
              }
            ]
          },
          "at": {
            "type": "string"
          },
          "comment": {
            "anyOf": [
              {
                "$ref": "#/definitions/Comment"
              },
              {
                "type": "null"
              }
            ]
          },
          "event": {
            "type": "string"
          },
          "ticket": {
            "$ref": "#/definitions/TicketPayload"
          },
          "ticket_id": {
            "type": "string"
          },
          "ticket_key": {
            "type": "string"
          }
        },
        "required": [
          "at",
          "event",
          "ticket",
          "ticket_id",
          "ticket_key"
        ],
        "title": "ChangeEvent",
        "type": "object"
      }
    },
    {
      "description": "Fires when a comment is added to one ticket, optionally filtered by author. Config: { ticket_id, author?, exclude_author?, root_only? }.",
      "invocation_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "TicketDetail": {
            "description": "How much of the ticket a delivery carries. `full` is the ticket with its comments and activity inline; `summary` is the board-card projection (key, title, status, priority, assignee, labels, order, timestamps, comment_count) — the right choice for an agent that re-reads the ticket with `kanban::ticket::get` anyway.",
            "enum": [
              "full",
              "summary"
            ],
            "type": "string"
          }
        },
        "properties": {
          "author": {
            "description": "Fire only for comments by exactly this author.",
            "type": [
              "string",
              "null"
            ]
          },
          "exclude_author": {
            "description": "Fire for every author except this one — pass your own profile id.",
            "type": [
              "string",
              "null"
            ]
          },
          "root_only": {
            "description": "Ignore replies; fire only for top-level comments.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "ticket": {
            "anyOf": [
              {
                "$ref": "#/definitions/TicketDetail"
              },
              {
                "type": "null"
              }
            ],
            "description": "`full` (default) delivers the whole ticket; `summary` only its board-card fields."
          },
          "ticket_id": {
            "description": "Required: ticket uuid or human key. A binding without it never fires.",
            "type": "string"
          }
        },
        "required": [
          "ticket_id"
        ],
        "title": "CommentConfig",
        "type": "object"
      },
      "metadata": {},
      "name": "kanban:comment",
      "return_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "Activity": {
            "properties": {
              "actor": {
                "type": "string"
              },
              "at": {
                "type": "string"
              },
              "changes": {
                "items": {
                  "$ref": "#/definitions/Change"
                },
                "type": [
                  "array",
                  "null"
                ]
              },
              "comment_id": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "id": {
                "type": "string"
              },
              "seq": {
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "ticket_id": {
                "type": "string"
              },
              "type": {
                "description": "ticket.created | ticket.updated | ticket.moved | ticket.deleted | ticket.restored | comment.created",
                "type": "string"
              }
            },
            "required": [
              "actor",
              "at",
              "id",
              "seq",
              "ticket_id",
              "type"
            ],
            "type": "object"
          },
          "Change": {
            "properties": {
              "field": {
                "type": "string"
              },
              "from": true,
              "to": true
            },
            "required": [
              "field",
              "from",
              "to"
            ],
            "type": "object"
          },
          "Comment": {
            "properties": {
              "author": {
                "description": "Agent profile id, or `user`.",
                "type": "string"
              },
              "body": {
                "type": "string"
              },
              "created_at": {
                "type": "string"
              },
              "id": {
                "type": "string"
              },
              "parent_id": {
                "default": null,
                "description": "Set for a reply; replies stay one level deep.",
                "type": [
                  "string",
                  "null"
                ]
              },
              "ticket_id": {
                "type": "string"
              }
            },
            "required": [
              "author",
              "body",
              "created_at",
              "id",
              "ticket_id"
            ],
            "type": "object"
          },
          "Ticket": {
            "properties": {
              "activity": {
                "default": [],
                "items": {
                  "$ref": "#/definitions/Activity"
                },
                "type": "array"
              },
              "assignee": {
                "default": null,
                "description": "Agent profile id.",
                "type": [
                  "string",
                  "null"
                ]
              },
              "comments": {
                "default": [],
                "items": {
                  "$ref": "#/definitions/Comment"
                },
                "type": "array"
              },
              "created_at": {
                "type": "string"
              },
              "created_by": {
                "default": "user",
                "type": "string"
              },
              "deleted_at": {
                "default": null,
                "description": "Set when soft-deleted; the row stays on disk.",
                "type": [
                  "string",
                  "null"
                ]
              },
              "description": {
                "default": "",
                "type": "string"
              },
              "id": {
                "description": "Internal uuid.",
                "type": "string"
              },
              "key": {
                "description": "Human-readable id, e.g. KAN-1.",
                "type": "string"
              },
              "labels": {
                "default": [],
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              "order": {
                "default": 0,
                "description": "Position inside its column.",
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "priority": {
                "type": "string"
              },
              "status": {
                "description": "Column id.",
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "updated_at": {
                "type": "string"
              }
            },
            "required": [
              "created_at",
              "id",
              "key",
              "priority",
              "status",
              "title",
              "updated_at"
            ],
            "type": "object"
          },
          "TicketPayload": {
            "anyOf": [
              {
                "$ref": "#/definitions/Ticket"
              },
              {
                "$ref": "#/definitions/TicketSummary"
              }
            ],
            "description": "The `ticket` field of a delivery: the whole ticket, or its summary when the binding asked for `ticket: summary`."
          },
          "TicketSummary": {
            "description": "The board-card projection of a ticket.",
            "properties": {
              "assignee": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "comment_count": {
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "created_at": {
                "type": "string"
              },
              "deleted_at": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "id": {
                "type": "string"
              },
              "key": {
                "type": "string"
              },
              "labels": {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              "order": {
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "priority": {
                "type": "string"
              },
              "status": {
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "updated_at": {
                "type": "string"
              }
            },
            "required": [
              "comment_count",
              "created_at",
              "id",
              "key",
              "labels",
              "order",
              "priority",
              "status",
              "title",
              "updated_at"
            ],
            "type": "object"
          }
        },
        "properties": {
          "at": {
            "type": "string"
          },
          "author": {
            "type": "string"
          },
          "comment": {
            "$ref": "#/definitions/Comment"
          },
          "event": {
            "description": "Always `comment.created`.",
            "type": "string"
          },
          "ticket": {
            "$ref": "#/definitions/TicketPayload"
          },
          "ticket_id": {
            "type": "string"
          },
          "ticket_key": {
            "type": "string"
          }
        },
        "required": [
          "at",
          "author",
          "comment",
          "event",
          "ticket",
          "ticket_id",
          "ticket_key"
        ],
        "title": "CommentEvent",
        "type": "object"
      }
    }
  ]
}

Search the registry

Find workers, kits and executables, or jump to a page.