{
  "components": {
    "schemas": {
      "AssetCard": {
        "additionalProperties": false,
        "description": "The short form of an asset: enough to show it in a list without reading its body.",
        "properties": {
          "id": {
            "description": "The asset's id.",
            "title": "Id",
            "type": "string"
          },
          "summary": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "A one- or two-line summary, or null when the asset's type has none.",
            "title": "Summary"
          },
          "tags": {
            "description": "The asset's tags.",
            "items": {
              "type": "string"
            },
            "title": "Tags",
            "type": "array"
          },
          "title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "A short title, or null when the asset's type has none.",
            "title": "Title"
          }
        },
        "required": [
          "id",
          "tags"
        ],
        "title": "AssetCard",
        "type": "object"
      },
      "AssetLink": {
        "additionalProperties": false,
        "description": "One relationship an asset has.",
        "properties": {
          "direction": {
            "description": "Whether it leaves this asset or arrives at it.",
            "title": "Direction",
            "type": "string"
          },
          "directionality": {
            "description": "Whether the relationship reads the same in both directions.",
            "title": "Directionality",
            "type": "string"
          },
          "neighbour": {
            "$ref": "#/components/schemas/AssetNeighbour",
            "description": "The asset at the other end."
          },
          "predicate": {
            "description": "The relationship's name.",
            "title": "Predicate",
            "type": "string"
          },
          "rank": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The position of this relationship among those of the same kind, or null when the relationship has no order.",
            "title": "Rank"
          },
          "version": {
            "description": "How many times this relationship has changed.",
            "title": "Version",
            "type": "integer"
          }
        },
        "required": [
          "predicate",
          "direction",
          "directionality",
          "version",
          "neighbour"
        ],
        "title": "AssetLink",
        "type": "object"
      },
      "AssetLinks": {
        "additionalProperties": false,
        "description": "An asset's relationships.",
        "properties": {
          "incoming": {
            "description": "Relationships that point at this asset.",
            "items": {
              "$ref": "#/components/schemas/AssetLink"
            },
            "title": "Incoming",
            "type": "array"
          },
          "outgoing": {
            "description": "Relationships that start at this asset.",
            "items": {
              "$ref": "#/components/schemas/AssetLink"
            },
            "title": "Outgoing",
            "type": "array"
          }
        },
        "required": [
          "outgoing",
          "incoming"
        ],
        "title": "AssetLinks",
        "type": "object"
      },
      "AssetNeighbour": {
        "additionalProperties": false,
        "description": "The asset at the other end of a relationship.",
        "properties": {
          "asset_id": {
            "description": "Its id.",
            "title": "Asset Id",
            "type": "string"
          },
          "asset_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Its type, or null if the id cannot be resolved.",
            "title": "Asset Type"
          },
          "label": {
            "description": "Its display name.",
            "title": "Label",
            "type": "string"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Its canonical name, `projects/{project}/assets/{asset_id}`. A request that takes an asset id in its body or query accepts this name in its place; a URL path takes the bare id. It is null when the id cannot be written in a canonical name.",
            "title": "Name"
          }
        },
        "required": [
          "asset_id",
          "label"
        ],
        "title": "AssetNeighbour",
        "type": "object"
      },
      "AssetResponse": {
        "additionalProperties": false,
        "description": "One asset.",
        "properties": {
          "asset": {
            "additionalProperties": true,
            "description": "The asset's whole body; its fields depend on the asset's type.",
            "title": "Asset",
            "type": "object"
          },
          "asset_id": {
            "description": "The asset's id.",
            "title": "Asset Id",
            "type": "string"
          },
          "asset_type": {
            "description": "The asset's type.",
            "title": "Asset Type",
            "type": "string"
          },
          "card": {
            "$ref": "#/components/schemas/AssetCard",
            "description": "The asset's short form."
          },
          "label": {
            "description": "The asset's display name.",
            "title": "Label",
            "type": "string"
          },
          "links": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AssetLinks"
              },
              {
                "type": "null"
              }
            ],
            "description": "The asset's relationships. Present when `expand=links` was asked for."
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The asset's canonical name, `projects/{project}/assets/{asset_id}`. A request that takes an asset id in its body or query accepts this name in its place; a URL path takes the bare id. It is null when the id cannot be written in a canonical name.",
            "title": "Name"
          },
          "noun": {
            "description": "What an asset of this type is called.",
            "title": "Noun",
            "type": "string"
          }
        },
        "required": [
          "asset_id",
          "asset_type",
          "noun",
          "label",
          "card",
          "asset"
        ],
        "title": "AssetResponse",
        "type": "object"
      },
      "AssetSummary": {
        "additionalProperties": false,
        "description": "One asset in a list.",
        "properties": {
          "asset": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "The asset's whole body. Present unless the list was requested with `view=index`; its fields depend on the asset's type.",
            "title": "Asset"
          },
          "asset_id": {
            "description": "The asset's id.",
            "title": "Asset Id",
            "type": "string"
          },
          "asset_type": {
            "description": "The asset's type.",
            "title": "Asset Type",
            "type": "string"
          },
          "card": {
            "$ref": "#/components/schemas/AssetCard",
            "description": "The asset's short form."
          },
          "label": {
            "description": "The asset's display name.",
            "title": "Label",
            "type": "string"
          },
          "last_updated": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the asset last changed. Present with `view=index`.",
            "title": "Last Updated"
          },
          "last_updated_by": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Who last changed the asset. Present with `view=index`.",
            "title": "Last Updated By"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The asset's canonical name, `projects/{project}/assets/{asset_id}`. A request that takes an asset id in its body or query accepts this name in its place; a URL path takes the bare id. It is null when the id cannot be written in a canonical name.",
            "title": "Name"
          },
          "noun": {
            "description": "What an asset of this type is called.",
            "title": "Noun",
            "type": "string"
          },
          "version": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The asset's version. Present with `view=index`.",
            "title": "Version"
          }
        },
        "required": [
          "asset_id",
          "asset_type",
          "noun",
          "label",
          "card"
        ],
        "title": "AssetSummary",
        "type": "object"
      },
      "AssetTypeEntry": {
        "additionalProperties": false,
        "description": "One asset type the project can hold.",
        "properties": {
          "asset_type": {
            "description": "The type's name; the value to pass as `asset_type` elsewhere.",
            "title": "Asset Type",
            "type": "string"
          },
          "card": {
            "additionalProperties": true,
            "description": "Which of the type's fields feed an asset's card: its title, summary and tags.",
            "title": "Card",
            "type": "object"
          },
          "content_schema": {
            "description": "The fields of an asset of this type, with their declared limits.",
            "items": {
              "$ref": "#/components/schemas/AssetTypeField"
            },
            "title": "Content Schema",
            "type": "array"
          },
          "custom": {
            "description": "True for a type the project declared itself, false for a built-in one.",
            "title": "Custom",
            "type": "boolean"
          },
          "declared_schema": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "For a type the project declared itself, the JSON Schema its assets' content must satisfy; absent for a built-in type, whose fields are in `content_schema`.",
            "title": "Declared Schema"
          },
          "display_label": {
            "description": "The name to show a person.",
            "title": "Display Label",
            "type": "string"
          },
          "enabled": {
            "description": "Whether the project can currently use the type.",
            "title": "Enabled",
            "type": "boolean"
          },
          "kit_role": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The role a kit holds assets of this type in (`contains`, `offers` or `carries`), or null for a type a kit cannot hold.",
            "title": "Kit Role"
          },
          "noun": {
            "description": "What one asset of this type is called.",
            "title": "Noun",
            "type": "string"
          },
          "object_type": {
            "description": "The id prefix assets of this type carry.",
            "title": "Object Type",
            "type": "string"
          },
          "purpose": {
            "description": "What the type is for.",
            "title": "Purpose",
            "type": "string"
          },
          "table": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "For a type the project declared as a table: its `key_column`, typed `columns`, `max_rows` and `rows_field`; null for every other type.",
            "title": "Table"
          },
          "when_not_to_use": {
            "description": "When another type is the better choice.",
            "title": "When Not To Use",
            "type": "string"
          },
          "when_to_use": {
            "description": "When to create an asset of this type.",
            "title": "When To Use",
            "type": "string"
          }
        },
        "required": [
          "asset_type",
          "object_type",
          "noun",
          "purpose",
          "when_to_use",
          "when_not_to_use",
          "display_label",
          "card",
          "enabled",
          "custom",
          "content_schema"
        ],
        "title": "AssetTypeEntry",
        "type": "object"
      },
      "AssetTypeField": {
        "additionalProperties": false,
        "description": "One field of an asset type's body.",
        "properties": {
          "cardinality": {
            "description": "Whether the field holds one value or many.",
            "title": "Cardinality",
            "type": "string"
          },
          "declared_max": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The most items or entries the field may hold, when limited.",
            "title": "Declared Max"
          },
          "description": {
            "description": "What the field is for.",
            "title": "Description",
            "type": "string"
          },
          "enum": {
            "anyOf": [
              {
                "items": {},
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "The only values the field accepts, when it is restricted to a set.",
            "title": "Enum"
          },
          "kind": {
            "description": "What kind of value it holds, for example text, a list or a map.",
            "title": "Kind",
            "type": "string"
          },
          "mime_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The media type of the field's content, when it has a fixed one.",
            "title": "Mime Type"
          },
          "mime_type_field": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The name of another field that says this field's media type, when it varies.",
            "title": "Mime Type Field"
          },
          "name": {
            "description": "The field's name.",
            "title": "Name",
            "type": "string"
          },
          "required": {
            "description": "Whether the field must be present.",
            "title": "Required",
            "type": "boolean"
          }
        },
        "required": [
          "name",
          "kind",
          "description",
          "required",
          "cardinality"
        ],
        "title": "AssetTypeField",
        "type": "object"
      },
      "AssetTypesResponse": {
        "additionalProperties": false,
        "description": "The asset types a project can hold, and the relationships its assets may have.",
        "properties": {
          "asset_types": {
            "description": "Every asset type, built-in and project-declared.",
            "items": {
              "$ref": "#/components/schemas/AssetTypeEntry"
            },
            "title": "Asset Types",
            "type": "array"
          },
          "link_floor": {
            "description": "The relationships any asset may have, and between which kinds.",
            "items": {
              "$ref": "#/components/schemas/LinkRule"
            },
            "title": "Link Floor",
            "type": "array"
          }
        },
        "required": [
          "asset_types",
          "link_floor"
        ],
        "title": "AssetTypesResponse",
        "type": "object"
      },
      "AssetsByIdEntry": {
        "additionalProperties": false,
        "description": "One asset returned by id.",
        "properties": {
          "asset": {
            "additionalProperties": true,
            "description": "The asset's whole body; its fields depend on the asset's type.",
            "title": "Asset",
            "type": "object"
          },
          "asset_type": {
            "description": "The asset's type.",
            "title": "Asset Type",
            "type": "string"
          },
          "declared_type": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "For an asset of a type the project declared: that type's card rules, content schema and, when it is a table, its table spec.",
            "title": "Declared Type"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The asset's canonical name, `projects/{project}/assets/{id}`, where `{id}` is the `id` inside `asset`. A request that takes an asset id in its body or query accepts this name in its place; a URL path takes the bare id. It is null when the id cannot be written in a canonical name.",
            "title": "Name"
          },
          "noun": {
            "description": "What an asset of this type is called.",
            "title": "Noun",
            "type": "string"
          }
        },
        "required": [
          "asset_type",
          "noun",
          "asset"
        ],
        "title": "AssetsByIdEntry",
        "type": "object"
      },
      "AssetsByIdResponse": {
        "additionalProperties": false,
        "description": "The assets that were asked for by id.",
        "properties": {
          "assets": {
            "description": "The assets the project holds, in no particular order.",
            "items": {
              "$ref": "#/components/schemas/AssetsByIdEntry"
            },
            "title": "Assets",
            "type": "array"
          },
          "not_found": {
            "description": "The ids that were asked for and are not in `assets`.",
            "items": {
              "type": "string"
            },
            "title": "Not Found",
            "type": "array"
          }
        },
        "required": [
          "assets",
          "not_found"
        ],
        "title": "AssetsByIdResponse",
        "type": "object"
      },
      "AssetsResponse": {
        "additionalProperties": false,
        "description": "A list of assets.",
        "properties": {
          "assets": {
            "description": "The assets, in a stable order.",
            "items": {
              "$ref": "#/components/schemas/AssetSummary"
            },
            "title": "Assets",
            "type": "array"
          },
          "resolved": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ResolvedRelease"
              },
              {
                "type": "null"
              }
            ],
            "description": "The release the list was read as. Present once the project has a release."
          },
          "total": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "How many assets match before `limit` and `offset` were applied. Present only when a window was requested.",
            "title": "Total"
          }
        },
        "required": [
          "assets"
        ],
        "title": "AssetsResponse",
        "type": "object"
      },
      "ChangesetDetail": {
        "additionalProperties": false,
        "description": "The open changeset as `GET changeset` reads it, with its ops grouped for review.",
        "properties": {
          "base_release": {
            "description": "The release the changeset was opened against. Send it back when staging.",
            "title": "Base Release",
            "type": "integer"
          },
          "base_repository_revision": {
            "description": "A fingerprint of the repository state the changeset was opened against.",
            "title": "Base Repository Revision",
            "type": "string"
          },
          "changeset_id": {
            "description": "The changeset's id.",
            "title": "Changeset Id",
            "type": "string"
          },
          "decision_summary": {
            "$ref": "#/components/schemas/DecisionSummary",
            "description": "How many ops have been decided."
          },
          "invalidated_by_release": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The release that made this changeset impossible to merge, if one did.",
            "title": "Invalidated By Release"
          },
          "items": {
            "description": "The ops grouped into the units a reviewer decides: everything staged on one asset, or on one relationship, together, with the names resolved.",
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Items",
            "type": "array"
          },
          "merge_claimed_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "When a publication claimed the changeset, while one is in progress.",
            "title": "Merge Claimed At"
          },
          "next_seq": {
            "description": "The position the next staged op will take.",
            "title": "Next Seq",
            "type": "integer"
          },
          "opened_at": {
            "description": "When the changeset was opened.",
            "title": "Opened At",
            "type": "string"
          },
          "opened_by": {
            "additionalProperties": true,
            "description": "Who opened it and why.",
            "title": "Opened By",
            "type": "object"
          },
          "ops": {
            "description": "Every op staged so far, in order.",
            "items": {
              "$ref": "#/components/schemas/ChangesetOp"
            },
            "title": "Ops",
            "type": "array"
          },
          "project_id": {
            "description": "The project the changeset belongs to.",
            "title": "Project Id",
            "type": "string"
          },
          "published_release": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The release it produced, once published.",
            "title": "Published Release"
          },
          "revision": {
            "description": "The changeset's revision. It changes every time the changeset does; send it back when staging.",
            "title": "Revision",
            "type": "integer"
          },
          "settled_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "When it was published or abandoned.",
            "title": "Settled At"
          },
          "settled_by": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Who settled it.",
            "title": "Settled By"
          },
          "status": {
            "description": "Whether the changeset is open or how it was settled.",
            "title": "Status",
            "type": "string"
          },
          "superseded_op_ids": {
            "description": "Ops that a later op overwrote.",
            "items": {
              "type": "string"
            },
            "title": "Superseded Op Ids",
            "type": "array"
          }
        },
        "required": [
          "project_id",
          "changeset_id",
          "status",
          "revision",
          "next_seq",
          "ops",
          "base_release",
          "base_repository_revision",
          "opened_at",
          "opened_by",
          "superseded_op_ids",
          "decision_summary",
          "items"
        ],
        "title": "ChangesetDetail",
        "type": "object"
      },
      "ChangesetOp": {
        "additionalProperties": false,
        "description": "One staged op and what has been decided about it.",
        "properties": {
          "carried_from": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The changeset the op was carried over from, if it was.",
            "title": "Carried From"
          },
          "carried_to": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The changeset the op was carried over to, if it was.",
            "title": "Carried To"
          },
          "cascaded_from": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The op whose rejection caused this one to be rejected, if any.",
            "title": "Cascaded From"
          },
          "conflict": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Why the op cannot merge as it stands, when something it depends on has moved; null otherwise.",
            "title": "Conflict"
          },
          "decided_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "When it was decided.",
            "title": "Decided At"
          },
          "decided_by": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Who decided and why, once someone has; null while the op is undecided.",
            "title": "Decided By"
          },
          "decision": {
            "description": "Where review stands: undecided, approved or rejected.",
            "title": "Decision",
            "type": "string"
          },
          "decision_history": {
            "description": "Every decision made about the op, oldest first.",
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Decision History",
            "type": "array"
          },
          "op": {
            "additionalProperties": true,
            "description": "The op as it was sent; its `op` field names the kind. `GET changeset` leaves out an upsert's `content` and the value of a patch's edit, which `GET changeset/ops` returns.",
            "title": "Op",
            "type": "object"
          },
          "op_id": {
            "description": "The id the service assigned when the op was staged. Use it to remove the op.",
            "title": "Op Id",
            "type": "string"
          },
          "reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The reason given for a rejection.",
            "title": "Reason"
          },
          "review_key": {
            "description": "Groups the ops a reviewer decides together.",
            "title": "Review Key",
            "type": "string"
          },
          "seq": {
            "description": "The op's position in the changeset, in staging order.",
            "title": "Seq",
            "type": "integer"
          },
          "staged_at": {
            "description": "When the op was staged.",
            "title": "Staged At",
            "type": "string"
          },
          "staged_by": {
            "additionalProperties": true,
            "description": "Who staged it and why.",
            "title": "Staged By",
            "type": "object"
          },
          "status": {
            "description": "The op's state in the changeset.",
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "op_id",
          "seq",
          "op",
          "staged_at",
          "staged_by",
          "decision",
          "decision_history",
          "review_key",
          "status"
        ],
        "title": "ChangesetOp",
        "type": "object"
      },
      "ChangesetOpsResponse": {
        "additionalProperties": false,
        "description": "Whole ops of the open changeset.",
        "properties": {
          "ops": {
            "description": "The ops asked for, in the order their ids were given, each with its full body.",
            "items": {
              "$ref": "#/components/schemas/ChangesetOp"
            },
            "title": "Ops",
            "type": "array"
          }
        },
        "required": [
          "ops"
        ],
        "title": "ChangesetOpsResponse",
        "type": "object"
      },
      "ChangesetRecord": {
        "additionalProperties": false,
        "description": "The open changeset: the proposed change and where review stands.",
        "properties": {
          "base_release": {
            "description": "The release the changeset was opened against. Send it back when staging.",
            "title": "Base Release",
            "type": "integer"
          },
          "base_repository_revision": {
            "description": "A fingerprint of the repository state the changeset was opened against.",
            "title": "Base Repository Revision",
            "type": "string"
          },
          "changeset_id": {
            "description": "The changeset's id.",
            "title": "Changeset Id",
            "type": "string"
          },
          "decision_summary": {
            "$ref": "#/components/schemas/DecisionSummary",
            "description": "How many ops have been decided."
          },
          "invalidated_by_release": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The release that made this changeset impossible to merge, if one did.",
            "title": "Invalidated By Release"
          },
          "merge_claimed_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "When a publication claimed the changeset, while one is in progress.",
            "title": "Merge Claimed At"
          },
          "next_seq": {
            "description": "The position the next staged op will take.",
            "title": "Next Seq",
            "type": "integer"
          },
          "opened_at": {
            "description": "When the changeset was opened.",
            "title": "Opened At",
            "type": "string"
          },
          "opened_by": {
            "additionalProperties": true,
            "description": "Who opened it and why.",
            "title": "Opened By",
            "type": "object"
          },
          "ops": {
            "description": "Every op staged so far, in order.",
            "items": {
              "$ref": "#/components/schemas/ChangesetOp"
            },
            "title": "Ops",
            "type": "array"
          },
          "project_id": {
            "description": "The project the changeset belongs to.",
            "title": "Project Id",
            "type": "string"
          },
          "published_release": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The release it produced, once published.",
            "title": "Published Release"
          },
          "revision": {
            "description": "The changeset's revision. It changes every time the changeset does; send it back when staging.",
            "title": "Revision",
            "type": "integer"
          },
          "settled_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "When it was published or abandoned.",
            "title": "Settled At"
          },
          "settled_by": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Who settled it.",
            "title": "Settled By"
          },
          "status": {
            "description": "Whether the changeset is open or how it was settled.",
            "title": "Status",
            "type": "string"
          },
          "superseded_op_ids": {
            "description": "Ops that a later op overwrote.",
            "items": {
              "type": "string"
            },
            "title": "Superseded Op Ids",
            "type": "array"
          }
        },
        "required": [
          "project_id",
          "changeset_id",
          "status",
          "revision",
          "next_seq",
          "ops",
          "base_release",
          "base_repository_revision",
          "opened_at",
          "opened_by",
          "superseded_op_ids",
          "decision_summary"
        ],
        "title": "ChangesetRecord",
        "type": "object"
      },
      "ChangesetResponse": {
        "additionalProperties": false,
        "description": "The open changeset without its op bodies, and the base to stage against. An op's body is `GET changeset/ops`.",
        "properties": {
          "base_release": {
            "description": "The release to send as `expected_release` when staging.",
            "title": "Base Release",
            "type": "integer"
          },
          "changeset": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ChangesetDetail"
              },
              {
                "type": "null"
              }
            ],
            "description": "The open changeset, or null when nothing is open. Each op names what it acts on and carries everything but its body: an upsert has no `content` and a patch's edit has no value."
          },
          "revision": {
            "description": "The changeset revision to send as `expected_revision` when staging; 0 when nothing is open.",
            "title": "Revision",
            "type": "integer"
          }
        },
        "required": [
          "base_release",
          "revision"
        ],
        "title": "ChangesetResponse",
        "type": "object"
      },
      "ChangesetsResponse": {
        "additionalProperties": false,
        "description": "The project's changesets, newest first: the open one and every one that was merged, closed or invalidated.",
        "properties": {
          "changesets": {
            "description": "Each changeset as the history lists it: its status, release, counts and its ops, in short form with `view=summary` and whole with `view=full`.",
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Changesets",
            "type": "array"
          }
        },
        "required": [
          "changesets"
        ],
        "title": "ChangesetsResponse",
        "type": "object"
      },
      "CloseBody": {
        "additionalProperties": false,
        "description": "The optional body of closing a change request.",
        "properties": {
          "carry_over": {
            "default": false,
            "description": "Keep the rejections as decided and move every undecided op to a new changeset opened on the same release, instead of rejecting everything. Allowed only when nothing is approved and at least one op is rejected.",
            "title": "Carry Over",
            "type": "boolean"
          },
          "expected_revision": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The changeset revision you looked at. When it has moved the call is a 409.",
            "title": "Expected Revision"
          },
          "provenance": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Who closed it and why, for the revision journal. Omit to have it filled in from the key.",
            "title": "Provenance"
          }
        },
        "title": "CloseBody",
        "type": "object"
      },
      "ContextVersionsResponse": {
        "additionalProperties": false,
        "description": "The versions of one context object.",
        "properties": {
          "body": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "The object's body as it was at that version; its fields depend on the object's type.",
            "title": "Body"
          },
          "object_id": {
            "description": "The object's id.",
            "title": "Object Id",
            "type": "string"
          },
          "version": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The version whose body is returned. Present when `version` was asked for.",
            "title": "Version"
          },
          "versions": {
            "description": "Every version the object has had, oldest first.",
            "items": {
              "type": "integer"
            },
            "title": "Versions",
            "type": "array"
          }
        },
        "required": [
          "object_id",
          "versions"
        ],
        "title": "ContextVersionsResponse",
        "type": "object"
      },
      "DecideBody": {
        "additionalProperties": false,
        "description": "The body of a review decision on one op or on every undecided op.",
        "properties": {
          "decision": {
            "description": "`approved` or `rejected`; `undecided` returns one op to review (it is refused when deciding every undecided op).",
            "enum": [
              "approved",
              "rejected",
              "undecided"
            ],
            "title": "Decision",
            "type": "string"
          },
          "expected_revision": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The changeset revision you were looking at. When it has moved the call is a 409, so a decision never lands on something you did not see.",
            "title": "Expected Revision"
          },
          "provenance": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Who decided and why, for the revision journal. Omit to have it filled in from the key.",
            "title": "Provenance"
          },
          "reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Why, kept with the decision. Worth giving for a rejection.",
            "title": "Reason"
          }
        },
        "required": [
          "decision"
        ],
        "title": "DecideBody",
        "type": "object"
      },
      "DecideOpsBody": {
        "additionalProperties": false,
        "description": "The body of a review decision on a named set of ops.",
        "properties": {
          "decision": {
            "description": "`approved` or `rejected`; `undecided` returns one op to review (it is refused when deciding every undecided op).",
            "enum": [
              "approved",
              "rejected",
              "undecided"
            ],
            "title": "Decision",
            "type": "string"
          },
          "expected_revision": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The changeset revision you were looking at. When it has moved the call is a 409, so a decision never lands on something you did not see.",
            "title": "Expected Revision"
          },
          "op_ids": {
            "description": "The ops to decide together, as `GET changeset` lists them. Name every op of a review item or none of it.",
            "items": {
              "type": "string"
            },
            "title": "Op Ids",
            "type": "array"
          },
          "provenance": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Who decided and why, for the revision journal. Omit to have it filled in from the key.",
            "title": "Provenance"
          },
          "reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Why, kept with the decision. Worth giving for a rejection.",
            "title": "Reason"
          }
        },
        "required": [
          "decision",
          "op_ids"
        ],
        "title": "DecideOpsBody",
        "type": "object"
      },
      "DecisionResponse": {
        "additionalProperties": false,
        "description": "The changeset after review decided some of its ops.",
        "properties": {
          "cascaded_op_ids": {
            "description": "Ops rejected because they depend on an op this call rejected.",
            "items": {
              "type": "string"
            },
            "title": "Cascaded Op Ids",
            "type": "array"
          },
          "changeset": {
            "$ref": "#/components/schemas/ChangesetRecord",
            "description": "The open changeset as it stands after the decision."
          },
          "decided_op_ids": {
            "description": "The ops whose decision this call changed.",
            "items": {
              "type": "string"
            },
            "title": "Decided Op Ids",
            "type": "array"
          }
        },
        "required": [
          "changeset",
          "decided_op_ids",
          "cascaded_op_ids"
        ],
        "title": "DecisionResponse",
        "type": "object"
      },
      "DecisionSummary": {
        "additionalProperties": false,
        "description": "How many ops review has decided.",
        "properties": {
          "approved": {
            "description": "Ops approved.",
            "title": "Approved",
            "type": "integer"
          },
          "rejected": {
            "description": "Ops rejected.",
            "title": "Rejected",
            "type": "integer"
          },
          "undecided": {
            "description": "Ops still waiting for a decision.",
            "title": "Undecided",
            "type": "integer"
          }
        },
        "required": [
          "approved",
          "rejected",
          "undecided"
        ],
        "title": "DecisionSummary",
        "type": "object"
      },
      "GapCreate": {
        "additionalProperties": false,
        "description": "The body that records a piece of context debt at version 1.",
        "properties": {
          "detail": {
            "description": "What is missing and what it was needed for, in plain language.",
            "minLength": 1,
            "title": "Detail",
            "type": "string"
          },
          "evidence": {
            "default": "",
            "description": "The excerpt or reasoning that surfaced it.",
            "title": "Evidence",
            "type": "string"
          },
          "id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Leave out: the service mints the gap's id.",
            "title": "Id"
          },
          "kind": {
            "description": "A short label for the sort of debt, such as `missing_tool`, `missing_skill` or `missing_knowledge`. Any short label is accepted.",
            "minLength": 1,
            "title": "Kind",
            "type": "string"
          },
          "metadata": {
            "additionalProperties": {
              "type": "string"
            },
            "description": "Free-form key-value pairs.",
            "title": "Metadata",
            "type": "object"
          },
          "opened_release": {
            "anyOf": [
              {
                "minimum": 0.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The context release the gap is opened under. Leave out for the latest release.",
            "title": "Opened Release"
          },
          "origin_context_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The recorded run it was discovered in.",
            "title": "Origin Context Id"
          },
          "rationale": {
            "default": "",
            "description": "Why, recorded in the gap's journal.",
            "title": "Rationale",
            "type": "string"
          },
          "tags": {
            "description": "Free-form labels.",
            "items": {
              "type": "string"
            },
            "title": "Tags",
            "type": "array"
          }
        },
        "required": [
          "kind",
          "detail"
        ],
        "title": "GapCreate",
        "type": "object"
      },
      "GapJournalRecord": {
        "additionalProperties": false,
        "description": "One change to a gap.",
        "properties": {
          "actor_kind": {
            "description": "`person` or `automation`.",
            "title": "Actor Kind",
            "type": "string"
          },
          "author": {
            "description": "Who made it.",
            "title": "Author",
            "type": "string"
          },
          "change_kind": {
            "description": "What kind of change it was: `created`, `content_updated` or `deleted`.",
            "title": "Change Kind",
            "type": "string"
          },
          "closed_release": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The release this closure was recorded under, the one its `covered_by` assets are read at. Empty for an entry that is not a closure.",
            "title": "Closed Release"
          },
          "covered_by": {
            "description": "On a retirement, the assets the closure named as covering the debt (possibly none).",
            "items": {
              "type": "string"
            },
            "title": "Covered By",
            "type": "array"
          },
          "rationale": {
            "description": "Why, when the author said.",
            "title": "Rationale",
            "type": "string"
          },
          "summary": {
            "description": "What changed, in a line.",
            "title": "Summary",
            "type": "string"
          },
          "timestamp": {
            "description": "When it happened.",
            "title": "Timestamp",
            "type": "string"
          },
          "version": {
            "description": "The version the change made.",
            "title": "Version",
            "type": "integer"
          }
        },
        "required": [
          "version",
          "timestamp",
          "author",
          "actor_kind",
          "change_kind",
          "summary",
          "rationale",
          "covered_by"
        ],
        "title": "GapJournalRecord",
        "type": "object"
      },
      "GapJournalResponse": {
        "additionalProperties": false,
        "description": "A gap's change journal, oldest first.",
        "properties": {
          "gap_id": {
            "description": "The gap's id.",
            "title": "Gap Id",
            "type": "string"
          },
          "journal": {
            "description": "Every change to the gap.",
            "items": {
              "$ref": "#/components/schemas/GapJournalRecord"
            },
            "title": "Journal",
            "type": "array"
          }
        },
        "required": [
          "gap_id",
          "journal"
        ],
        "title": "GapJournalResponse",
        "type": "object"
      },
      "GapKitRecord": {
        "additionalProperties": false,
        "description": "A kit that carries a gap.",
        "properties": {
          "id": {
            "description": "The kit's id.",
            "title": "Id",
            "type": "string"
          },
          "title": {
            "description": "The kit's title.",
            "title": "Title",
            "type": "string"
          },
          "version": {
            "description": "The kit version that holds the gap.",
            "title": "Version",
            "type": "integer"
          }
        },
        "required": [
          "id",
          "title",
          "version"
        ],
        "title": "GapKitRecord",
        "type": "object"
      },
      "GapPatch": {
        "additionalProperties": false,
        "description": "The body that changes a gap's fields. Only the fields you send change.",
        "properties": {
          "base_version": {
            "description": "The gap version you read. A gap that has moved is a 409.",
            "title": "Base Version",
            "type": "integer"
          },
          "detail": {
            "anyOf": [
              {
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "A sharper description of what is missing.",
            "title": "Detail"
          },
          "evidence": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "New evidence text.",
            "title": "Evidence"
          },
          "kind": {
            "anyOf": [
              {
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "A new kind label.",
            "title": "Kind"
          },
          "metadata": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "The complete new key-value pairs.",
            "title": "Metadata"
          },
          "origin_context_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "A different run it was discovered in.",
            "title": "Origin Context Id"
          },
          "rationale": {
            "default": "",
            "description": "Why, recorded in the gap's journal.",
            "title": "Rationale",
            "type": "string"
          },
          "tags": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "The complete new tag list.",
            "title": "Tags"
          }
        },
        "required": [
          "base_version"
        ],
        "title": "GapPatch",
        "type": "object"
      },
      "GapResponse": {
        "additionalProperties": false,
        "description": "A gap: a piece of recorded context debt, something an agent needed that the context did not have. A gap is not an asset: it has its own versions and its own change journal, is written directly and is never part of a release.",
        "properties": {
          "closed_release": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The release that covered the gap. Empty while the gap is still open.",
            "title": "Closed Release"
          },
          "content_key": {
            "description": "What makes two reports one open debt: a digest of the kind and the detail.",
            "title": "Content Key",
            "type": "string"
          },
          "detail": {
            "description": "What is missing and what it was needed for.",
            "title": "Detail",
            "type": "string"
          },
          "evidence": {
            "description": "The excerpt or reasoning that surfaced it.",
            "title": "Evidence",
            "type": "string"
          },
          "id": {
            "description": "The gap's id.",
            "title": "Id",
            "type": "string"
          },
          "kind": {
            "description": "A short label for the sort of debt: `missing_tool`, `missing_skill`, `missing_knowledge` or any other short label.",
            "title": "Kind",
            "type": "string"
          },
          "kits": {
            "description": "The kits that carry this gap.",
            "items": {
              "$ref": "#/components/schemas/GapKitRecord"
            },
            "title": "Kits",
            "type": "array"
          },
          "last_changed_by": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Who last changed the gap.",
            "title": "Last Changed By"
          },
          "last_changed_by_kind": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "`person` or `automation`.",
            "title": "Last Changed By Kind"
          },
          "last_updated": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the gap last changed.",
            "title": "Last Updated"
          },
          "last_updated_by": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Whether the last change was made by a person (`human`) or by an automation (`ai`).",
            "title": "Last Updated By"
          },
          "metadata": {
            "additionalProperties": {
              "type": "string"
            },
            "description": "The gap's free-form key-value pairs.",
            "title": "Metadata",
            "type": "object"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The gap's canonical name, `projects/{project}/gaps/{id}`. It is null when the id cannot be written in a canonical name.",
            "title": "Name"
          },
          "opened_release": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The context release the gap was opened under. Provenance only: a gap is served from live state.",
            "title": "Opened Release"
          },
          "origin_context_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The recorded run it was discovered in.",
            "title": "Origin Context Id"
          },
          "retired": {
            "description": "Whether the gap has been closed.",
            "title": "Retired",
            "type": "boolean"
          },
          "tags": {
            "description": "The gap's free-form labels.",
            "items": {
              "type": "string"
            },
            "title": "Tags",
            "type": "array"
          },
          "version": {
            "description": "The gap's version. It moves each time the gap is changed, retired or reverted.",
            "title": "Version",
            "type": "integer"
          }
        },
        "required": [
          "id",
          "version",
          "kind",
          "detail",
          "evidence",
          "tags",
          "metadata",
          "content_key",
          "retired",
          "kits"
        ],
        "title": "GapResponse",
        "type": "object"
      },
      "GapRetire": {
        "additionalProperties": false,
        "description": "The body that closes a gap, naming what covers it.",
        "properties": {
          "base_version": {
            "description": "The gap version you read. A gap that has moved is a 409.",
            "title": "Base Version",
            "type": "integer"
          },
          "closed_release": {
            "anyOf": [
              {
                "minimum": 0.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The release that covered the gap. Leave out for the latest release.",
            "title": "Closed Release"
          },
          "covered_by": {
            "description": "Optional. The ids of the assets that cover the debt: zero or more, each an asset of the release the closure is recorded under, else a 422 naming it.",
            "items": {
              "type": "string"
            },
            "title": "Covered By",
            "type": "array"
          },
          "expected_release": {
            "anyOf": [
              {
                "minimum": 0.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Expected Release"
          },
          "rationale": {
            "default": "",
            "description": "Why, recorded in the gap's journal.",
            "title": "Rationale",
            "type": "string"
          }
        },
        "required": [
          "base_version"
        ],
        "title": "GapRetire",
        "type": "object"
      },
      "GapRevert": {
        "additionalProperties": false,
        "description": "The body that appends an earlier version's definition as the gap's next version; it reopens a retired gap.",
        "properties": {
          "base_version": {
            "description": "The gap version you read. A gap that has moved is a 409.",
            "title": "Base Version",
            "type": "integer"
          },
          "rationale": {
            "default": "",
            "description": "Why, recorded in the gap's journal.",
            "title": "Rationale",
            "type": "string"
          },
          "to_version": {
            "description": "The earlier version whose definition to restore.",
            "title": "To Version",
            "type": "integer"
          }
        },
        "required": [
          "base_version",
          "to_version"
        ],
        "title": "GapRevert",
        "type": "object"
      },
      "GapsResponse": {
        "additionalProperties": false,
        "description": "The project's gaps.",
        "properties": {
          "gaps": {
            "description": "The gaps asked for, by id.",
            "items": {
              "$ref": "#/components/schemas/GapResponse"
            },
            "title": "Gaps",
            "type": "array"
          }
        },
        "required": [
          "gaps"
        ],
        "title": "GapsResponse",
        "type": "object"
      },
      "HTTPValidationError": {
        "description": "The body of a `422`: the request was well-formed but a parameter or the body failed validation.",
        "properties": {
          "detail": {
            "description": "One entry for each problem found.",
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "title": "Detail",
            "type": "array"
          }
        },
        "title": "HTTPValidationError",
        "type": "object"
      },
      "KitAddMembers": {
        "additionalProperties": false,
        "description": "The body that adds assets to a kit.",
        "properties": {
          "base_version": {
            "description": "The kit version you read. A kit that has moved is a 409.",
            "title": "Base Version",
            "type": "integer"
          },
          "members": {
            "description": "The assets to add. At least one.",
            "items": {
              "$ref": "#/components/schemas/KitMemberInput"
            },
            "minItems": 1,
            "title": "Members",
            "type": "array"
          },
          "rationale": {
            "default": "",
            "description": "Why, recorded in the kit's journal.",
            "title": "Rationale",
            "type": "string"
          }
        },
        "required": [
          "base_version",
          "members"
        ],
        "title": "KitAddMembers",
        "type": "object"
      },
      "KitChangelogResponse": {
        "additionalProperties": false,
        "description": "What changed in a kit, and in everything it holds, over its history.",
        "properties": {
          "journal": {
            "description": "The revisions behind the summary, newest first.",
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Journal",
            "type": "array"
          },
          "kit_id": {
            "description": "The kit's id.",
            "title": "Kit Id",
            "type": "string"
          },
          "summary": {
            "description": "One entry per kit version, newest first, saying what changed in it.",
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Summary",
            "type": "array"
          }
        },
        "required": [
          "kit_id",
          "summary",
          "journal"
        ],
        "title": "KitChangelogResponse",
        "type": "object"
      },
      "KitCreate": {
        "additionalProperties": false,
        "description": "The body that creates a kit at version 1.",
        "properties": {
          "auto_maintain": {
            "default": false,
            "description": "Opt the kit in to automatic upkeep of its members. Off by default.",
            "title": "Auto Maintain",
            "type": "boolean"
          },
          "description": {
            "default": "",
            "description": "What the kit is for.",
            "title": "Description",
            "type": "string"
          },
          "id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Leave out: the service mints the kit's id.",
            "title": "Id"
          },
          "members": {
            "description": "The assets the kit holds from the start, in serving order.",
            "items": {
              "$ref": "#/components/schemas/KitMemberInput"
            },
            "title": "Members",
            "type": "array"
          },
          "metadata": {
            "additionalProperties": {
              "type": "string"
            },
            "description": "Free-form key-value pairs.",
            "title": "Metadata",
            "type": "object"
          },
          "rationale": {
            "default": "",
            "description": "Why, recorded in the kit's journal.",
            "title": "Rationale",
            "type": "string"
          },
          "tags": {
            "description": "Free-form labels.",
            "items": {
              "type": "string"
            },
            "title": "Tags",
            "type": "array"
          },
          "title": {
            "description": "The kit's title.",
            "minLength": 1,
            "title": "Title",
            "type": "string"
          }
        },
        "required": [
          "title"
        ],
        "title": "KitCreate",
        "type": "object"
      },
      "KitEntry": {
        "additionalProperties": false,
        "description": "A skill a kit holds and the tools it binds.",
        "properties": {
          "skill_id": {
            "description": "The skill's id.",
            "title": "Skill Id",
            "type": "string"
          },
          "skill_name": {
            "description": "The skill's name.",
            "title": "Skill Name",
            "type": "string"
          },
          "tool_ids": {
            "description": "The ids of the tools the skill binds.",
            "items": {
              "type": "string"
            },
            "title": "Tool Ids",
            "type": "array"
          }
        },
        "required": [
          "skill_id",
          "skill_name",
          "tool_ids"
        ],
        "title": "KitEntry",
        "type": "object"
      },
      "KitFullResponse": {
        "additionalProperties": false,
        "description": "A kit with every asset it serves, bodies included, in one read.",
        "properties": {
          "assets": {
            "additionalProperties": {
              "additionalProperties": true,
              "type": "object"
            },
            "description": "Every served asset keyed by its id. Each asset's fields depend on its type.",
            "title": "Assets",
            "type": "object"
          },
          "kit": {
            "$ref": "#/components/schemas/KitResponse",
            "description": "The kit itself."
          },
          "kit_id": {
            "description": "The kit's id.",
            "title": "Kit Id",
            "type": "string"
          },
          "members": {
            "additionalProperties": {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            "description": "The ids of what the kit served, grouped by asset type.",
            "title": "Members",
            "type": "object"
          },
          "resolved": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ResolvedRelease"
              },
              {
                "type": "null"
              }
            ],
            "description": "The release the assets were read at, with its tags."
          }
        },
        "required": [
          "kit_id",
          "members",
          "assets",
          "kit"
        ],
        "title": "KitFullResponse",
        "type": "object"
      },
      "KitIgnoredMemberRecord": {
        "additionalProperties": false,
        "description": "A held asset the kit did not serve at the release the read named, and why.",
        "properties": {
          "member": {
            "$ref": "#/components/schemas/KitMemberRecord",
            "description": "The held asset."
          },
          "reason": {
            "description": "`retired` (a release retired it and nothing replaced it), `superseded` (a release retired it and the successors below were served in its place) or `unpublished` (the pinned release does not contain it yet).",
            "title": "Reason",
            "type": "string"
          },
          "successor_ids": {
            "description": "The assets served in its place, in order. Empty unless `superseded`.",
            "items": {
              "type": "string"
            },
            "title": "Successor Ids",
            "type": "array"
          }
        },
        "required": [
          "member",
          "reason",
          "successor_ids"
        ],
        "title": "KitIgnoredMemberRecord",
        "type": "object"
      },
      "KitJournalRecord": {
        "additionalProperties": false,
        "description": "One change to a kit.",
        "properties": {
          "actor_kind": {
            "description": "`person` or `automation`.",
            "title": "Actor Kind",
            "type": "string"
          },
          "author": {
            "description": "Who made it.",
            "title": "Author",
            "type": "string"
          },
          "change_kind": {
            "description": "What kind of change it was.",
            "title": "Change Kind",
            "type": "string"
          },
          "rationale": {
            "description": "Why, when the author said.",
            "title": "Rationale",
            "type": "string"
          },
          "refs": {
            "description": "The assets the change added or removed.",
            "items": {
              "type": "string"
            },
            "title": "Refs",
            "type": "array"
          },
          "summary": {
            "description": "What changed, in a line.",
            "title": "Summary",
            "type": "string"
          },
          "timestamp": {
            "description": "When it happened.",
            "title": "Timestamp",
            "type": "string"
          },
          "version": {
            "description": "The version the change made.",
            "title": "Version",
            "type": "integer"
          }
        },
        "required": [
          "version",
          "timestamp",
          "author",
          "actor_kind",
          "change_kind",
          "summary",
          "rationale",
          "refs"
        ],
        "title": "KitJournalRecord",
        "type": "object"
      },
      "KitJournalResponse": {
        "additionalProperties": false,
        "description": "A kit's change journal, oldest first.",
        "properties": {
          "journal": {
            "description": "Every change to the kit.",
            "items": {
              "$ref": "#/components/schemas/KitJournalRecord"
            },
            "title": "Journal",
            "type": "array"
          },
          "kit_id": {
            "description": "The kit's id.",
            "title": "Kit Id",
            "type": "string"
          }
        },
        "required": [
          "kit_id",
          "journal"
        ],
        "title": "KitJournalResponse",
        "type": "object"
      },
      "KitMemberInput": {
        "additionalProperties": false,
        "description": "An asset to put in a kit, and optionally where.",
        "properties": {
          "asset_id": {
            "description": "The asset's id. It must exist; a kit cannot hold another kit.",
            "title": "Asset Id",
            "type": "string"
          },
          "rank": {
            "anyOf": [
              {
                "minimum": 0.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Where in the kit's order of that role the asset goes. Leave out to append.",
            "title": "Rank"
          },
          "role": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/KitRole"
              },
              {
                "type": "null"
              }
            ],
            "description": "Leave out. The role follows from the asset's type."
          }
        },
        "required": [
          "asset_id"
        ],
        "title": "KitMemberInput",
        "type": "object"
      },
      "KitMemberRecord": {
        "additionalProperties": false,
        "description": "One asset a kit holds.",
        "properties": {
          "asset_id": {
            "description": "The held asset's id.",
            "title": "Asset Id",
            "type": "string"
          },
          "asset_kind": {
            "description": "The kind the id names: `skill`, `knowledge`, `tool`, `gap`, `memory`, `example`, `pointer` or `asset`.",
            "title": "Asset Kind",
            "type": "string"
          },
          "rank": {
            "description": "Its place within the role. Ranks are sparse, so an asset can be put between two others without renumbering them.",
            "title": "Rank",
            "type": "integer"
          },
          "role": {
            "description": "How the kit holds it: `contains`, `offers` or `carries`.",
            "title": "Role",
            "type": "string"
          }
        },
        "required": [
          "asset_id",
          "asset_kind",
          "role",
          "rank"
        ],
        "title": "KitMemberRecord",
        "type": "object"
      },
      "KitPatch": {
        "additionalProperties": false,
        "description": "The body that changes a kit's own fields. Only the fields you send change.",
        "properties": {
          "auto_maintain": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "description": "Turn automatic upkeep of the kit's members on or off.",
            "title": "Auto Maintain"
          },
          "base_version": {
            "description": "The kit version you read. A kit that has moved is a 409.",
            "title": "Base Version",
            "type": "integer"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "A new description.",
            "title": "Description"
          },
          "metadata": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "The complete new key-value pairs.",
            "title": "Metadata"
          },
          "rationale": {
            "default": "",
            "description": "Why, recorded in the kit's journal.",
            "title": "Rationale",
            "type": "string"
          },
          "tags": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "The complete new tag list.",
            "title": "Tags"
          },
          "title": {
            "anyOf": [
              {
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "A new title.",
            "title": "Title"
          }
        },
        "required": [
          "base_version"
        ],
        "title": "KitPatch",
        "type": "object"
      },
      "KitResponse": {
        "additionalProperties": false,
        "description": "A context kit: a named, versioned selection of assets an agent is given for a kind of work. A kit is not an asset: it has its own versions and its own change journal, and a release never changes one.",
        "properties": {
          "auto_maintain": {
            "description": "Whether the kit has opted in to automatic upkeep of its members. Off by default.",
            "title": "Auto Maintain",
            "type": "boolean"
          },
          "description": {
            "description": "What the kit is for.",
            "title": "Description",
            "type": "string"
          },
          "entries": {
            "description": "The kit's skills and the tools each binds.",
            "items": {
              "$ref": "#/components/schemas/KitEntry"
            },
            "title": "Entries",
            "type": "array"
          },
          "gaps": {
            "description": "Knowledge gaps the kit carries.",
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Gaps",
            "type": "array"
          },
          "id": {
            "description": "The kit's id.",
            "title": "Id",
            "type": "string"
          },
          "ignored_members": {
            "description": "Members the release this read named could not serve, with the reason. Empty when nothing was skipped.",
            "items": {
              "$ref": "#/components/schemas/KitIgnoredMemberRecord"
            },
            "title": "Ignored Members",
            "type": "array"
          },
          "last_changed_by": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Who last changed the kit.",
            "title": "Last Changed By"
          },
          "last_changed_by_kind": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "`person` or `automation`.",
            "title": "Last Changed By Kind"
          },
          "last_updated": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the kit last changed.",
            "title": "Last Updated"
          },
          "last_updated_by": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Whether a person (`human`) or an automation (`ai`) last changed the kit.",
            "title": "Last Updated By"
          },
          "member_cards": {
            "anyOf": [
              {
                "additionalProperties": {
                  "items": {
                    "$ref": "#/components/schemas/AssetCard"
                  },
                  "type": "array"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "The short form of each served asset, grouped by asset type.",
            "title": "Member Cards"
          },
          "member_roles": {
            "additionalProperties": {
              "type": "string"
            },
            "description": "For each kind of asset id, the role a kit holds it in.",
            "title": "Member Roles",
            "type": "object"
          },
          "members": {
            "description": "What this version of the kit holds, in serving order.",
            "items": {
              "$ref": "#/components/schemas/KitMemberRecord"
            },
            "title": "Members",
            "type": "array"
          },
          "members_by_type": {
            "additionalProperties": {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            "description": "The ids of the assets the kit served at that release, grouped by asset type.",
            "title": "Members By Type",
            "type": "object"
          },
          "metadata": {
            "additionalProperties": {
              "type": "string"
            },
            "description": "The kit's free-form key-value pairs.",
            "title": "Metadata",
            "type": "object"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The kit's canonical name, `projects/{project}/kits/{id}`. A request that takes a kit id in its body or query accepts this name in its place; a URL path takes the bare id. It is null when the id cannot be written in a canonical name.",
            "title": "Name"
          },
          "project_id": {
            "description": "The project the kit belongs to.",
            "title": "Project Id",
            "type": "string"
          },
          "release": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The release this read resolved the kit's assets at.",
            "title": "Release"
          },
          "retired": {
            "description": "Whether the kit has been retired.",
            "title": "Retired",
            "type": "boolean"
          },
          "tags": {
            "description": "The kit's free-form labels.",
            "items": {
              "type": "string"
            },
            "title": "Tags",
            "type": "array"
          },
          "title": {
            "description": "The kit's title.",
            "title": "Title",
            "type": "string"
          },
          "version": {
            "description": "The kit's version. It moves when the kit's fields or its members change.",
            "title": "Version",
            "type": "integer"
          },
          "versions": {
            "anyOf": [
              {
                "items": {
                  "type": "integer"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Every version the kit has had. Present when a kit is read.",
            "title": "Versions"
          }
        },
        "required": [
          "id",
          "version",
          "title",
          "description",
          "tags",
          "metadata",
          "auto_maintain",
          "retired",
          "project_id",
          "members",
          "ignored_members",
          "members_by_type",
          "member_roles",
          "entries",
          "gaps"
        ],
        "title": "KitResponse",
        "type": "object"
      },
      "KitRevert": {
        "additionalProperties": false,
        "description": "The body that appends an earlier version's definition as the kit's next version.",
        "properties": {
          "base_version": {
            "description": "The kit version you read. A kit that has moved is a 409.",
            "title": "Base Version",
            "type": "integer"
          },
          "rationale": {
            "default": "",
            "description": "Why, recorded in the kit's journal.",
            "title": "Rationale",
            "type": "string"
          },
          "to_version": {
            "description": "The earlier version whose fields and members to restore.",
            "title": "To Version",
            "type": "integer"
          }
        },
        "required": [
          "base_version",
          "to_version"
        ],
        "title": "KitRevert",
        "type": "object"
      },
      "KitRole": {
        "description": "How a kit holds a member: `contains` for skills, knowledge, memories, examples, pointers and custom types, `offers` for tools, `carries` for knowledge gaps.",
        "enum": [
          "contains",
          "offers",
          "carries"
        ],
        "title": "KitRole",
        "type": "string"
      },
      "KitsResponse": {
        "additionalProperties": false,
        "description": "The project's kits.",
        "properties": {
          "kits": {
            "description": "The current version of every live kit.",
            "items": {
              "$ref": "#/components/schemas/KitResponse"
            },
            "title": "Kits",
            "type": "array"
          }
        },
        "required": [
          "kits"
        ],
        "title": "KitsResponse",
        "type": "object"
      },
      "LineageResponse": {
        "additionalProperties": false,
        "description": "Where one version of an object came from: the revision that wrote it and the evidence and edits behind that.",
        "properties": {
          "object_id": {
            "description": "The object's id.",
            "title": "Object Id",
            "type": "string"
          },
          "root": {
            "additionalProperties": true,
            "description": "The revision that made this version. Its `children` are what it was derived from, each with its own children, so the whole chain can be walked; every earlier version's own revision follows, newest first, so the lineage is cumulative.",
            "title": "Root",
            "type": "object"
          },
          "version": {
            "description": "The version traced.",
            "title": "Version",
            "type": "integer"
          }
        },
        "required": [
          "object_id",
          "version",
          "root"
        ],
        "title": "LineageResponse",
        "type": "object"
      },
      "LinkRule": {
        "additionalProperties": false,
        "description": "A relationship the project's assets may have.",
        "properties": {
          "bidirectional": {
            "description": "Whether the relationship reads the same in both directions.",
            "title": "Bidirectional",
            "type": "boolean"
          },
          "endpoint_asset_types": {
            "description": "A narrower set of asset types the two ends may be, when the relationship is restricted.",
            "title": "Endpoint Asset Types"
          },
          "from_kinds": {
            "description": "The kinds of asset it may start from.",
            "items": {
              "type": "string"
            },
            "title": "From Kinds",
            "type": "array"
          },
          "predicate": {
            "description": "The relationship's name.",
            "title": "Predicate",
            "type": "string"
          },
          "to_kinds": {
            "description": "The kinds of asset it may point to.",
            "items": {
              "type": "string"
            },
            "title": "To Kinds",
            "type": "array"
          }
        },
        "required": [
          "predicate",
          "from_kinds",
          "to_kinds",
          "bidirectional"
        ],
        "title": "LinkRule",
        "type": "object"
      },
      "MergeBody": {
        "additionalProperties": false,
        "description": "The optional body of a merge.",
        "properties": {
          "changeset_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The changeset you mean to merge. Omit for the open one.",
            "title": "Changeset Id"
          },
          "expected_revision": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The changeset revision you reviewed. When it has moved the merge is a 409.",
            "title": "Expected Revision"
          },
          "provenance": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Who merged and why, for the revision journal. Omit to have it filled in from the key.",
            "title": "Provenance"
          },
          "tags": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Release tags to put on the release this merge makes.",
            "title": "Tags"
          }
        },
        "title": "MergeBody",
        "type": "object"
      },
      "MergeResponse": {
        "additionalProperties": false,
        "description": "What merging the change request published.",
        "properties": {
          "carried_op_ids": {
            "description": "The undecided ops that moved to that changeset.",
            "items": {
              "type": "string"
            },
            "title": "Carried Op Ids",
            "type": "array"
          },
          "carried_to_changeset_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The changeset that took over the ops nobody had decided, or null when there were none.",
            "title": "Carried To Changeset Id"
          },
          "changed_asset_ids": {
            "description": "The assets the merge wrote or changed.",
            "items": {
              "type": "string"
            },
            "title": "Changed Asset Ids",
            "type": "array"
          },
          "changeset_id": {
            "description": "The changeset that was merged.",
            "title": "Changeset Id",
            "type": "string"
          },
          "conflicted_op_ids": {
            "description": "Carried ops that no longer apply cleanly and need review again.",
            "items": {
              "type": "string"
            },
            "title": "Conflicted Op Ids",
            "type": "array"
          },
          "deleted_asset_ids": {
            "description": "The assets the merge retired.",
            "items": {
              "type": "string"
            },
            "title": "Deleted Asset Ids",
            "type": "array"
          },
          "object_versions": {
            "additionalProperties": {
              "type": "integer"
            },
            "description": "The version of every object as the new release publishes it.",
            "title": "Object Versions",
            "type": "object"
          },
          "ops_published": {
            "description": "How many approved ops were published.",
            "title": "Ops Published",
            "type": "integer"
          },
          "release": {
            "description": "The release the merge made.",
            "title": "Release",
            "type": "integer"
          }
        },
        "required": [
          "changeset_id",
          "release",
          "ops_published",
          "changed_asset_ids",
          "deleted_asset_ids",
          "object_versions",
          "carried_op_ids",
          "conflicted_op_ids"
        ],
        "title": "MergeResponse",
        "type": "object"
      },
      "ObjectHistoryResponse": {
        "additionalProperties": false,
        "description": "Every revision of one context object, oldest to newest.",
        "properties": {
          "history": {
            "description": "The revisions of the object. Each names the version it made, who wrote it, why and from which sources.",
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "History",
            "type": "array"
          },
          "object_id": {
            "description": "The object's id.",
            "title": "Object Id",
            "type": "string"
          }
        },
        "required": [
          "object_id",
          "history"
        ],
        "title": "ObjectHistoryResponse",
        "type": "object"
      },
      "ProjectIdentity": {
        "additionalProperties": false,
        "description": "The project the calling key resolves to.",
        "properties": {
          "environment": {
            "description": "The environment serving this project, such as `staging` or `demo`.",
            "title": "Environment",
            "type": "string"
          },
          "project_id": {
            "description": "The id of the project the key belongs to.",
            "title": "Project Id",
            "type": "string"
          }
        },
        "required": [
          "project_id",
          "environment"
        ],
        "title": "ProjectIdentity",
        "type": "object"
      },
      "ReleaseRecord": {
        "additionalProperties": false,
        "description": "One published state of the whole repository.",
        "properties": {
          "changeset_id": {
            "description": "The changeset whose publication made this release.",
            "title": "Changeset Id",
            "type": "string"
          },
          "changeset_revision": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The revision the changeset was at when it was published.",
            "title": "Changeset Revision"
          },
          "created_at": {
            "description": "When the release was made.",
            "title": "Created At",
            "type": "string"
          },
          "created_by": {
            "additionalProperties": true,
            "description": "Who published it and why.",
            "title": "Created By",
            "type": "object"
          },
          "deleted": {
            "description": "The ids of the objects this release retired.",
            "items": {
              "type": "string"
            },
            "title": "Deleted",
            "type": "array"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The release's canonical name, `projects/{project}/releases/{release}`. A request that takes a release in a query accepts this name in its place; a URL path takes the bare number. It is null when the id cannot be written in a canonical name.",
            "title": "Name"
          },
          "object_versions": {
            "additionalProperties": {
              "type": "integer"
            },
            "description": "The version of every object as this release published it.",
            "title": "Object Versions",
            "type": "object"
          },
          "project_id": {
            "description": "The project the release belongs to.",
            "title": "Project Id",
            "type": "string"
          },
          "release": {
            "description": "The release number. Each published change makes the next.",
            "title": "Release",
            "type": "integer"
          },
          "tag_history": {
            "description": "Every time a tag was added to or removed from this release, oldest first.",
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Tag History",
            "type": "array"
          },
          "tags": {
            "description": "The tags this release carries.",
            "items": {
              "type": "string"
            },
            "title": "Tags",
            "type": "array"
          }
        },
        "required": [
          "project_id",
          "release",
          "changeset_id",
          "created_at",
          "created_by",
          "object_versions",
          "deleted",
          "tags",
          "tag_history"
        ],
        "title": "ReleaseRecord",
        "type": "object"
      },
      "ReleasesResponse": {
        "additionalProperties": false,
        "description": "The project's releases, newest first.",
        "properties": {
          "latest": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The number of the latest release, or null before the first one.",
            "title": "Latest"
          },
          "releases": {
            "description": "The releases asked for.",
            "items": {
              "$ref": "#/components/schemas/ReleaseRecord"
            },
            "title": "Releases",
            "type": "array"
          }
        },
        "required": [
          "releases"
        ],
        "title": "ReleasesResponse",
        "type": "object"
      },
      "ReplaceTagsRequest": {
        "additionalProperties": false,
        "description": "The complete tag list a release should carry. An unknown key is a 422, so a misspelt `tags` cannot silently clear a release's tags.",
        "properties": {
          "tags": {
            "description": "Every tag the release should carry afterwards. It replaces the current list.",
            "items": {
              "type": "string"
            },
            "title": "Tags",
            "type": "array"
          }
        },
        "required": [
          "tags"
        ],
        "title": "ReplaceTagsRequest",
        "type": "object"
      },
      "ResolvedRelease": {
        "additionalProperties": false,
        "description": "The release a read was resolved at.",
        "properties": {
          "tags": {
            "description": "The tags that release carries.",
            "items": {
              "type": "string"
            },
            "title": "Tags",
            "type": "array"
          },
          "version": {
            "description": "The release number.",
            "title": "Version",
            "type": "integer"
          }
        },
        "required": [
          "version",
          "tags"
        ],
        "title": "ResolvedRelease",
        "type": "object"
      },
      "SearchQueryResults": {
        "additionalProperties": false,
        "description": "The results of one query of several.",
        "properties": {
          "query": {
            "description": "The query.",
            "title": "Query",
            "type": "string"
          },
          "results": {
            "description": "What it found, best first.",
            "items": {
              "$ref": "#/components/schemas/SearchResult"
            },
            "title": "Results",
            "type": "array"
          }
        },
        "required": [
          "query",
          "results"
        ],
        "title": "SearchQueryResults",
        "type": "object"
      },
      "SearchRequest": {
        "additionalProperties": false,
        "description": "The body of a search: what to look for and which asset types to search.",
        "properties": {
          "asset_type": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Restrict the search to these asset types, for example `skill` or `knowledge_page`. Omit to search every type. An unknown type is a 400.",
            "title": "Asset Type"
          },
          "max_results": {
            "default": 20,
            "description": "At most this many results, 20 by default. With `queries` it applies to each query, not to the total.",
            "minimum": 1.0,
            "title": "Max Results",
            "type": "integer"
          },
          "queries": {
            "anyOf": [
              {
                "items": {
                  "maxLength": 8000,
                  "type": "string"
                },
                "maxItems": 20,
                "minItems": 1,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Up to 20 independent searches, each answered on its own and returned in the same order. Send either `queries` or `query`, not both.",
            "title": "Queries"
          },
          "query": {
            "anyOf": [
              {
                "maxLength": 8000,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "What to search for. Send either `query` or `queries`, not both.",
            "title": "Query"
          }
        },
        "title": "SearchRequest",
        "type": "object"
      },
      "SearchResponse": {
        "additionalProperties": false,
        "description": "The results of a search. A single `query` answers with `query` and a flat `results`; `queries` answers with `queries` and one entry of `results` per query, in order.",
        "properties": {
          "queries": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "The queries, when several were sent.",
            "title": "Queries"
          },
          "query": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The query, when one was sent.",
            "title": "Query"
          },
          "results": {
            "description": "For one query, the assets it found, best first. For several, one entry per query, in the order sent.",
            "items": {
              "anyOf": [
                {
                  "$ref": "#/components/schemas/SearchResult"
                },
                {
                  "$ref": "#/components/schemas/SearchQueryResults"
                }
              ]
            },
            "title": "Results",
            "type": "array"
          }
        },
        "required": [
          "results"
        ],
        "title": "SearchResponse",
        "type": "object"
      },
      "SearchResult": {
        "additionalProperties": false,
        "description": "One asset a search found.",
        "properties": {
          "asset_id": {
            "description": "The asset's id.",
            "title": "Asset Id",
            "type": "string"
          },
          "asset_type": {
            "description": "The asset's type.",
            "title": "Asset Type",
            "type": "string"
          },
          "label": {
            "description": "The asset's display name.",
            "title": "Label",
            "type": "string"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The asset's canonical name, `projects/{project}/assets/{asset_id}`. A request that takes an asset id in its body or query accepts this name in its place; a URL path takes the bare id. It is null when the id cannot be written in a canonical name.",
            "title": "Name"
          },
          "rank": {
            "description": "The asset's position in the returned list, starting at 1.",
            "title": "Rank",
            "type": "integer"
          }
        },
        "required": [
          "asset_id",
          "asset_type",
          "label",
          "rank"
        ],
        "title": "SearchResult",
        "type": "object"
      },
      "SourcesResponse": {
        "additionalProperties": false,
        "description": "The sources an object's versions were written from.",
        "properties": {
          "lineage_only_versions": {
            "description": "Versions whose origin is recorded as a lineage but names no source.",
            "items": {
              "type": "integer"
            },
            "title": "Lineage Only Versions",
            "type": "array"
          },
          "object_id": {
            "description": "The object's id.",
            "title": "Object Id",
            "type": "string"
          },
          "sources": {
            "description": "Each source the object's history cites, with the versions that cite it.",
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Sources",
            "type": "array"
          },
          "unsourced_versions": {
            "description": "Versions that cite no source at all.",
            "items": {
              "type": "integer"
            },
            "title": "Unsourced Versions",
            "type": "array"
          }
        },
        "required": [
          "object_id",
          "sources",
          "unsourced_versions",
          "lineage_only_versions"
        ],
        "title": "SourcesResponse",
        "type": "object"
      },
      "StageOpsBody": {
        "description": "The body of a request to stage ops. The route reads and validates it itself; this describes it.",
        "properties": {
          "expected_release": {
            "anyOf": [
              {
                "minimum": 0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The release number the changeset was opened against, from `GET changeset`. Required: without it, or if it has moved, the call is refused with 409.",
            "title": "Expected Release"
          },
          "expected_revision": {
            "anyOf": [
              {
                "minimum": 0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The changeset revision you read, from `GET changeset`; 0 when nothing was open. Required: without it, or if the changeset has moved, the call is refused with 409.",
            "title": "Expected Revision"
          },
          "ops": {
            "description": "The ops to stage, in order, at most 100. Each is an object whose `op` field names what it does: `upsert_asset`, `patch_asset`, `delete_asset`, `add_link`, `remove_link` or `update_link`. Every op carries `base_version`, the version of what it changes that you read, or 0 when it creates. Wherever an op names an asset (`asset_id`, `from_id`, `to_id`) it may give the id or the canonical name.",
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "maxItems": 100,
            "minItems": 1,
            "title": "Ops",
            "type": "array"
          },
          "provenance": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Who is proposing the change and why.",
            "title": "Provenance"
          }
        },
        "required": [
          "ops"
        ],
        "title": "StageOpsBody",
        "type": "object"
      },
      "StageOpsResponse": {
        "additionalProperties": false,
        "description": "The open changeset after a batch was staged.",
        "properties": {
          "base_release": {
            "description": "The release the changeset was opened against. Send it back when staging.",
            "title": "Base Release",
            "type": "integer"
          },
          "base_repository_revision": {
            "description": "A fingerprint of the repository state the changeset was opened against.",
            "title": "Base Repository Revision",
            "type": "string"
          },
          "batch_ops": {
            "description": "The ops this call staged. They are also the last entries of `ops`.",
            "items": {
              "$ref": "#/components/schemas/ChangesetOp"
            },
            "title": "Batch Ops",
            "type": "array"
          },
          "changeset_id": {
            "description": "The changeset's id.",
            "title": "Changeset Id",
            "type": "string"
          },
          "decision_summary": {
            "$ref": "#/components/schemas/DecisionSummary",
            "description": "How many ops have been decided."
          },
          "invalidated_by_release": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The release that made this changeset impossible to merge, if one did.",
            "title": "Invalidated By Release"
          },
          "merge_claimed_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "When a publication claimed the changeset, while one is in progress.",
            "title": "Merge Claimed At"
          },
          "next_seq": {
            "description": "The position the next staged op will take.",
            "title": "Next Seq",
            "type": "integer"
          },
          "opened_at": {
            "description": "When the changeset was opened.",
            "title": "Opened At",
            "type": "string"
          },
          "opened_by": {
            "additionalProperties": true,
            "description": "Who opened it and why.",
            "title": "Opened By",
            "type": "object"
          },
          "ops": {
            "description": "Every op staged so far, in order.",
            "items": {
              "$ref": "#/components/schemas/ChangesetOp"
            },
            "title": "Ops",
            "type": "array"
          },
          "project_id": {
            "description": "The project the changeset belongs to.",
            "title": "Project Id",
            "type": "string"
          },
          "published_release": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The release it produced, once published.",
            "title": "Published Release"
          },
          "revision": {
            "description": "The changeset's revision. It changes every time the changeset does; send it back when staging.",
            "title": "Revision",
            "type": "integer"
          },
          "settled_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "When it was published or abandoned.",
            "title": "Settled At"
          },
          "settled_by": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Who settled it.",
            "title": "Settled By"
          },
          "status": {
            "description": "Whether the changeset is open or how it was settled.",
            "title": "Status",
            "type": "string"
          },
          "superseded_op_ids": {
            "description": "Ops that a later op overwrote.",
            "items": {
              "type": "string"
            },
            "title": "Superseded Op Ids",
            "type": "array"
          }
        },
        "required": [
          "project_id",
          "changeset_id",
          "status",
          "revision",
          "next_seq",
          "ops",
          "base_release",
          "base_repository_revision",
          "opened_at",
          "opened_by",
          "superseded_op_ids",
          "decision_summary",
          "batch_ops"
        ],
        "title": "StageOpsResponse",
        "type": "object"
      },
      "ValidationError": {
        "description": "One validation problem.",
        "properties": {
          "ctx": {
            "description": "Extra detail about the problem, when there is any.",
            "title": "Context",
            "type": "object"
          },
          "input": {
            "description": "The value that was rejected.",
            "title": "Input"
          },
          "loc": {
            "description": "Where the problem is: the part of the request, then the field's path.",
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            },
            "title": "Location",
            "type": "array"
          },
          "msg": {
            "description": "What is wrong, in words.",
            "title": "Message",
            "type": "string"
          },
          "type": {
            "description": "A short machine-readable name for the kind of problem.",
            "title": "Error Type",
            "type": "string"
          }
        },
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "title": "ValidationError",
        "type": "object"
      }
    },
    "securitySchemes": {
      "customerToken": {
        "bearerFormat": "JWT",
        "description": "A short-lived access token, obtained by exchanging an API key with the OAuth 2.0 client-credentials grant. Send it as `Authorization: Bearer <token>`. Each operation lists the scope the token must carry; there are five, and none implies another: `context:read` reads context; `context:assets` stages a change for review and never decides, merges or closes one; `context:review` approves or rejects staged ops and merges or closes the change request; `context:kits` writes kits directly and `context:gaps` records and closes gaps directly, each of which takes effect at once and bypasses the changeset.",
        "scheme": "bearer",
        "type": "http"
      }
    }
  },
  "info": {
    "title": "Context Repository Service",
    "version": "0.1.0"
  },
  "openapi": "3.1.0",
  "paths": {
    "/context/v1/asset-types": {
      "get": {
        "description": "Returns every asset type the project can hold: the built-in types and any the project declared itself. Each entry gives the type's display names, its fields with their media types and declared limits, and a `custom` flag that is true for a type the project declared. Call this first to learn what exists before listing or searching assets; the type names it returns are the values to pass as `asset_type` elsewhere.",
        "operationId": "list_asset_types_v1_asset_types_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetTypesResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:read"
            ]
          }
        ],
        "summary": "List asset types"
      }
    },
    "/context/v1/assets": {
      "get": {
        "description": "Lists the assets the project holds, of every type or of the types named in `asset_type`, optionally narrowed by a `label` substring or an `asset_tag`. Reads the live state by default, or the state a given `release` or `tag` published. Use `view=index` to list without bodies, and `limit` with `offset` to read a window; a windowed response also reports `total`. There is no implicit cap. An unknown asset type is a 400, and `status` is refused with a 400 because no asset type has one.",
        "operationId": "list_assets_v1_assets_get",
        "parameters": [
          {
            "description": "Restrict to these asset types, as a comma-separated list of type names such as `skill,tool`. Omit for every type. List the names with the asset-types operation. An unknown name is a 400.",
            "in": "query",
            "name": "asset_type",
            "required": false,
            "schema": {
              "default": "",
              "description": "Comma-separated wire words to filter by (`skill`, `kit`, `knowledge_page`, `knowledge_entity`, `tool`, `gap`). Omit for every type. An unknown word is a 400, never an empty list.",
              "title": "Asset Type",
              "type": "string"
            }
          },
          {
            "description": "Keep assets whose display name contains this text, ignoring case.",
            "in": "query",
            "name": "label",
            "required": false,
            "schema": {
              "default": "",
              "description": "Case-insensitive substring of the asset's display label.",
              "title": "Label",
              "type": "string"
            }
          },
          {
            "description": "Pass `links` to attach incoming and outgoing relationships, each with the neighbour's type and display name already resolved.",
            "in": "query",
            "name": "expand",
            "required": false,
            "schema": {
              "default": "",
              "description": "Comma-separated: `links` attaches each asset's resolved in/out edges; `mentions` attaches the derived mention index (ids it mentions / ids of the pages mentioning it) -- not links.",
              "title": "Expand",
              "type": "string"
            }
          },
          {
            "description": "Not supported: no asset type has a status, so any value is refused with a 400.",
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "default": "",
              "description": "REFUSED with 400. No asset type carries a status; see the route's own note. Declared so the refusal is explicit rather than a silent ignore.",
              "title": "Status",
              "type": "string"
            }
          },
          {
            "description": "Read the assets as this release published them: its number or its canonical name (`projects/{project}/releases/{n}`). Omit for the live state. An unknown release is a 404. Cannot be combined with `tag`.",
            "in": "query",
            "name": "release",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "A release number or a release's canonical name (`projects/{project}/releases/{n}`). Resolve the list as the named release published it (Assets table version selector). Omit for live/latest. Unknown release -> 404, mirroring `GET /v1/graph?release=N`. Mutually exclusive with `tag`.",
              "title": "Release"
            }
          },
          {
            "description": "Keep assets that carry this exact tag among their own `tags`. Not the same as `tag`, which names a release.",
            "in": "query",
            "name": "asset_tag",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Keep assets whose own `tags` (the free-form labels every asset carries) include this exact value. Named `asset_tag` because `tag` already means a RELEASE tag here.",
              "title": "Asset Tag"
            }
          },
          {
            "description": "Read the assets as the release currently holding this tag published them. A tag no release holds is a 404. Cannot be combined with `release`.",
            "in": "query",
            "name": "tag",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Resolve the list as the release currently holding this tag published it. A tag is exclusive, so at most one release holds it; a tag no release holds is 404, never an empty list. Mutually exclusive with `release`.",
              "title": "Tag"
            }
          },
          {
            "description": "`index` lists each asset without its body (identity, display name, card and version); `full`, the default, includes the body.",
            "in": "query",
            "name": "view",
            "required": false,
            "schema": {
              "default": "full",
              "description": "`index` lists each asset without its body \u2014 identity, label, card and version stamps \u2014 so a list does not download what only a detail view reads. `full` (the default) carries the body.",
              "enum": [
                "full",
                "index"
              ],
              "title": "View",
              "type": "string"
            }
          },
          {
            "description": "Return at most this many assets. Omit to return all of them.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "minimum": 1,
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Serve at most this many assets of the filtered set. Omit for the whole set \u2014 there is deliberately no implicit cap.",
              "title": "Limit"
            }
          },
          {
            "description": "Skip this many assets before returning.",
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "default": 0,
              "description": "Skip this many assets of the filtered set.",
              "minimum": 0,
              "title": "Offset",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetsResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:read"
            ]
          }
        ],
        "summary": "List assets"
      }
    },
    "/context/v1/assets/by-id": {
      "get": {
        "description": "Returns the named assets in one call, of whatever types their ids name. Pass the ids as a comma-separated list in `asset_ids`, at most 500 per call. Use it when you already hold ids, for example from a search or a link, and want their bodies without one request each. An id the project does not hold is left out of `assets` and listed in `not_found`.",
        "operationId": "assets_by_id_v1_assets_by_id_get",
        "parameters": [
          {
            "description": "Comma-separated asset ids or canonical names (`projects/{project}/assets/{id}`), at most 500.",
            "in": "query",
            "name": "asset_ids",
            "required": false,
            "schema": {
              "default": "",
              "title": "Asset Ids",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetsByIdResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:read"
            ]
          }
        ],
        "summary": "Get several assets by id"
      }
    },
    "/context/v1/assets/{asset_id}": {
      "get": {
        "description": "Returns one asset by its id; the id's prefix says which type it is. Pass `version` to read an archived version instead of the live one. Pass `expand=links` to attach the asset's incoming and outgoing relationships, each with the neighbour's type and display name already resolved, so you do not need a request per relationship.",
        "operationId": "get_asset_v1_assets__asset_id__get",
        "parameters": [
          {
            "description": "The asset's id.",
            "in": "path",
            "name": "asset_id",
            "required": true,
            "schema": {
              "title": "Asset Id",
              "type": "string"
            }
          },
          {
            "description": "Return this archived version of the asset instead of the live one.",
            "in": "query",
            "name": "version",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Return this version's ARCHIVED body instead of the live one \u2014 the same archive `GET /v1/context-versions/{object_id}?version=N` reads, through this generic surface. Omit for live.",
              "title": "Version"
            }
          },
          {
            "description": "Pass `links` to attach incoming and outgoing relationships, each with the neighbour's type and display name already resolved.",
            "in": "query",
            "name": "expand",
            "required": false,
            "schema": {
              "default": "",
              "description": "Comma-separated: `links` attaches this asset's resolved in/out edges; `mentions` its derived mention index, which is not a link.",
              "title": "Expand",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:read"
            ]
          }
        ],
        "summary": "Get an asset"
      }
    },
    "/context/v1/changeset": {
      "get": {
        "description": "Returns the project's open changeset without the bodies of its ops: its status, the ops staged in it (what each acts on, who staged it and how review has decided it), and the ops grouped into the units a reviewer decides. It stays fast however many ops are staged. Read `revision` and `base_release` from here immediately before you compute a batch to stage, because staging requires both back; they are returned when nothing is open too. An upsert's `content` and the value of a patch's edit are left out: read them with `GET changeset/ops`. A merge re-checks every op itself and refuses one that is stale or duplicates another, so nothing here needs to be worked out before you merge.",
        "operationId": "get_changeset_v1_changeset_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChangesetResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:read"
            ]
          }
        ],
        "summary": "Get the open changeset"
      }
    },
    "/context/v1/changeset/close": {
      "post": {
        "description": "Closes the open changeset without publishing it: every op is recorded as rejected, and nothing is served that was not served before. Set `carry_over` to keep the rejections you made and move the ops nobody decided to a new changeset on the same release, which is allowed only when nothing is approved and at least one op is rejected. A closed changeset stays in the history. Needs the review scope.",
        "operationId": "abandon_changeset_v1_changeset_close_post",
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "expected_revision": 3
              },
              "schema": {
                "$ref": "#/components/schemas/CloseBody"
              }
            }
          },
          "required": false
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChangesetRecord"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:review"
            ]
          }
        ],
        "summary": "Close the change request"
      }
    },
    "/context/v1/changeset/decide-outstanding": {
      "post": {
        "description": "Approves or rejects every op that has no decision yet, in one call, and never touches one already decided. This includes ops other people staged, so use it only when you have reviewed the whole changeset. A bulk approval that would include an op whose dependency is rejected is refused as a whole with a 409. `undecided` is not accepted here.",
        "operationId": "decide_outstanding_changeset_ops_v1_changeset_decide_outstanding_post",
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "decision": "approved",
                "expected_revision": 3
              },
              "schema": {
                "$ref": "#/components/schemas/DecideBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DecisionResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:review"
            ]
          }
        ],
        "summary": "Decide every undecided op"
      }
    },
    "/context/v1/changeset/decisions": {
      "post": {
        "description": "Approves or rejects the named ops together, as one decision. Name every op of each review item you include: naming only part of an item is a 409, and nothing is widened for you. Use it to settle exactly the ops you reviewed; use `POST changeset/decide-outstanding` only when you mean to decide everything undecided, including ops other people staged. Same rules and responses as deciding one op.",
        "operationId": "decide_changeset_ops_v1_changeset_decisions_post",
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "decision": "approved",
                "expected_revision": 3,
                "op_ids": [
                  "csop_example"
                ]
              },
              "schema": {
                "$ref": "#/components/schemas/DecideOpsBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DecisionResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:review"
            ]
          }
        ],
        "summary": "Decide several staged ops"
      }
    },
    "/context/v1/changeset/merge": {
      "post": {
        "description": "Publishes the approved ops: writes their bodies and makes the next release, which is what agents are served from then on. A merge touches assets only; a kit is written separately and directly, with the kits scope, and a merge never changes one. Ops nobody decided are not published; they carry over to a new changeset opened on the release this merge makes, and the response names it. Rejected ops stay on the merged changeset as the record. Nothing approved is a 422. The merge is a 409 when the changeset moved since you reviewed it (send `expected_revision`), or when another release was published after the changeset opened, in which case the changeset is settled `invalidated` and nothing is published. Needs the review scope.",
        "operationId": "publish_changeset_v1_changeset_merge_post",
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "expected_revision": 3,
                "tags": [
                  "production"
                ]
              },
              "schema": {
                "$ref": "#/components/schemas/MergeBody"
              }
            }
          },
          "required": false
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MergeResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:review"
            ]
          }
        ],
        "summary": "Merge the change request"
      }
    },
    "/context/v1/changeset/ops": {
      "get": {
        "description": "Returns whole ops of the open changeset, bodies included, for the ids you name. Use it to read what `GET changeset` leaves out: an upsert's `content` and the value of a patch's edit. Ops come back in the order you asked for them. Name at most 100 ids; more is a 422. An id that names no op of the open changeset is a 404 naming it, so a missing body is never returned as an empty one.",
        "operationId": "get_changeset_ops_v1_changeset_ops_get",
        "parameters": [
          {
            "description": "The op ids to read, comma-separated, from 1 to 100 of them, as `GET changeset` lists them.",
            "in": "query",
            "name": "ids",
            "required": true,
            "schema": {
              "description": "Op ids, comma-separated.",
              "title": "Ids",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChangesetOpsResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:read"
            ]
          }
        ],
        "summary": "Get staged ops"
      },
      "post": {
        "description": "Proposes a change: stages a batch of ops into the project's open changeset, opening one if none is open. It writes no version and publishes nothing, and a customer key cannot publish. Send `expected_revision` and `expected_release`, both read from the changeset just before you computed the batch; if either has moved the call is refused with 409 so you can re-read and recompute. A batch holds at most 100 ops. An invalid op, an unknown target or an oversized batch is a 422. Send an `Idempotency-Key` header to make a retry safe: a repeat of the same key and batch replays the first result, and reusing the key for a different batch is a 409. The response lists the whole open changeset; the last entries are the ones this call staged.",
        "operationId": "stage_changeset_ops_v1_changeset_ops_post",
        "parameters": [
          {
            "description": "Optional. Repeating a call with the same key and batch replays the first result instead of staging again; the same key with a different batch is a 409.",
            "in": "header",
            "name": "Idempotency-Key",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Idempotency-Key"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "expected_release": 0,
                "expected_revision": 0,
                "ops": [
                  {
                    "base_version": 0,
                    "from_id": "skill_example",
                    "op": "add_link",
                    "predicate": "references",
                    "to_id": "skill_example"
                  }
                ]
              },
              "schema": {
                "$ref": "#/components/schemas/StageOpsBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StageOpsResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:assets"
            ]
          }
        ],
        "summary": "Stage ops"
      }
    },
    "/context/v1/changeset/ops/{op_id}": {
      "delete": {
        "description": "Removes one op from the open changeset so the rest can be reviewed without it. Use it to retract a change you staged. Name the op by its `op_id`, which the service assigned when it was staged; it is not the op's position, so removing one op never renumbers the others.",
        "operationId": "remove_changeset_op_v1_changeset_ops__op_id__delete",
        "parameters": [
          {
            "description": "The id the service assigned to the op when it was staged.",
            "in": "path",
            "name": "op_id",
            "required": true,
            "schema": {
              "title": "Op Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChangesetRecord"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:assets"
            ]
          }
        ],
        "summary": "Remove a staged op"
      }
    },
    "/context/v1/changeset/ops/{op_id}/decision": {
      "post": {
        "description": "Approves or rejects one op of the open changeset, or returns it to undecided. Only approved ops are published by a merge. Rejecting an op also rejects every op that depends on it, listed in `cascaded_op_ids`. Approving an op whose dependency is rejected or undecided is a 409 naming it. The ops of one asset, or of one relationship, are one review item, and naming one op here decides every op of its item (`decided_op_ids` lists them all). To decide exactly the ops you name, use `POST changeset/decisions`, which refuses an item you name only part of. Send `expected_revision` so a decision never lands on a changeset that moved after you read it. Needs the review scope, which a key that can only stage does not hold.",
        "operationId": "decide_changeset_op_v1_changeset_ops__op_id__decision_post",
        "parameters": [
          {
            "description": "The id of the op, as `GET changeset` lists it.",
            "in": "path",
            "name": "op_id",
            "required": true,
            "schema": {
              "title": "Op Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "decision": "approved",
                "expected_revision": 3
              },
              "schema": {
                "$ref": "#/components/schemas/DecideBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DecisionResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:review"
            ]
          }
        ],
        "summary": "Decide one staged op"
      }
    },
    "/context/v1/changesets": {
      "get": {
        "description": "Returns the project's changesets, newest first: the open one and every one that was merged, closed or invalidated. Nothing is deleted, so a closed changeset is the record of what was turned down. `view=summary` lists each changeset's ops in short form (identity and who staged them, without edit bodies or review items); the default `full` view returns them whole.",
        "operationId": "list_changesets_v1_changesets_get",
        "parameters": [
          {
            "description": "Return at most this many changesets, from 1 to 200. Defaults to 50.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 50,
              "maximum": 200,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "description": "Skip this many changesets before returning. Defaults to 0.",
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "default": 0,
              "minimum": 0,
              "title": "Offset",
              "type": "integer"
            }
          },
          {
            "description": "`summary` returns each changeset's ops in short form, without edit bodies or review items; `full`, the default, returns them whole.",
            "in": "query",
            "name": "view",
            "required": false,
            "schema": {
              "default": "full",
              "description": "``summary`` is the lean read a table joins against: lifecycle, release, op count and each op's identity \u2014 no edit payloads, no review items, and none of the name resolution the items cost.",
              "enum": [
                "full",
                "summary"
              ],
              "title": "View",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChangesetsResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:read"
            ]
          }
        ],
        "summary": "List changesets"
      }
    },
    "/context/v1/context-history/{object_id}": {
      "get": {
        "description": "Returns every revision of one context object, oldest to newest: the version each made, who wrote it, why, and from which sources. Use `GET context-versions/{object_id}` to read the archived bodies themselves.",
        "operationId": "get_object_history_v1_context_history__object_id__get",
        "parameters": [
          {
            "description": "The id of the context object.",
            "in": "path",
            "name": "object_id",
            "required": true,
            "schema": {
              "title": "Object Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ObjectHistoryResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:read"
            ]
          }
        ],
        "summary": "Get an object's revisions"
      }
    },
    "/context/v1/context-history/{object_id}/lineage": {
      "get": {
        "description": "Returns the chain that produced one version of an object: the revision that wrote it, and beneath it the evidence and earlier edits it was derived from, each as a node with its own children. Defaults to the latest version.",
        "operationId": "get_object_lineage_v1_context_history__object_id__lineage_get",
        "parameters": [
          {
            "description": "The id of the context object.",
            "in": "path",
            "name": "object_id",
            "required": true,
            "schema": {
              "title": "Object Id",
              "type": "string"
            }
          },
          {
            "description": "Which version to trace. Defaults to the latest.",
            "in": "query",
            "name": "version",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Which version to trace \u2014 defaults to the latest recorded.",
              "title": "Version"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LineageResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:read"
            ]
          }
        ],
        "summary": "Trace where a version came from"
      }
    },
    "/context/v1/context-history/{object_id}/sources": {
      "get": {
        "description": "Returns every source an object's history cites, with the versions that cite each, and names the versions that cite none or only a lineage. Use it to see how well an asset's content is supported.",
        "operationId": "get_object_sources_v1_context_history__object_id__sources_get",
        "parameters": [
          {
            "description": "The id of the context object.",
            "in": "path",
            "name": "object_id",
            "required": true,
            "schema": {
              "title": "Object Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SourcesResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:read"
            ]
          }
        ],
        "summary": "List the sources behind an object"
      }
    },
    "/context/v1/context-versions/{object_id}": {
      "get": {
        "description": "Returns the versions of one context object. Without `version` it lists them; with `version` it also returns that version's archived body, so you can read what the object said before it changed. Versions are append-only, and a retired object keeps its history.",
        "operationId": "get_object_version_v1_context_versions__object_id__get",
        "parameters": [
          {
            "description": "The id of the context object.",
            "in": "path",
            "name": "object_id",
            "required": true,
            "schema": {
              "title": "Object Id",
              "type": "string"
            }
          },
          {
            "description": "Also return the archived body of this version. Omit to list the versions only.",
            "in": "query",
            "name": "version",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Return this version's body too. Omit for the version list only.",
              "title": "Version"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContextVersionsResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:read"
            ]
          }
        ],
        "summary": "Get an object's version history"
      }
    },
    "/context/v1/gaps": {
      "get": {
        "description": "Returns the project's gaps, by id. A gap is a piece of recorded context debt: something an agent needed that the context did not have. It is not an asset, so it is not listed with assets. By default only open gaps are returned; `state` asks for the retired ones or both, and `kind` keeps one sort of debt.",
        "operationId": "list_gaps_v1_gaps_get",
        "parameters": [
          {
            "description": "`open` (default), `retired` or `all`.",
            "in": "query",
            "name": "state",
            "required": false,
            "schema": {
              "default": "open",
              "description": "`open` (default), `retired` or `all`.",
              "title": "State",
              "type": "string"
            }
          },
          {
            "description": "Only gaps of this kind, such as `missing_tool`.",
            "in": "query",
            "name": "kind",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Only gaps of this kind.",
              "title": "Kind"
            }
          },
          {
            "description": "Only gaps opened under this release.",
            "in": "query",
            "name": "opened_release",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Only gaps opened under this release.",
              "title": "Opened Release"
            }
          },
          {
            "description": "Only gaps closed by this release.",
            "in": "query",
            "name": "closed_release",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Only gaps closed by this release.",
              "title": "Closed Release"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GapsResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:read"
            ]
          }
        ],
        "summary": "List gaps"
      },
      "post": {
        "description": "Records a piece of context debt at version 1 under the release named in `opened_release` (the latest when omitted). A gap takes effect at once, needs no review and no release. Two open gaps cannot share a kind and a detail: recording one that is already open is a 409 `duplicate_key` naming the gap that holds it; a hole found again after its gap was closed opens a new gap. A gap names no kit: add it to a kit with the kit members call, using the gap's id.",
        "operationId": "create_gap_v1_gaps_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GapCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GapResponse"
                }
              }
            },
            "description": "OK"
          },
          "201": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:gaps"
            ]
          }
        ],
        "summary": "Record a gap"
      }
    },
    "/context/v1/gaps/{gap_id}": {
      "get": {
        "description": "Returns one gap at its current version, or at the version given in `version`, with the kits that carry it. A retired gap is returned too, marked retired.",
        "operationId": "get_gap_v1_gaps__gap_id__get",
        "parameters": [
          {
            "description": "The gap's id.",
            "in": "path",
            "name": "gap_id",
            "required": true,
            "schema": {
              "title": "Gap Id",
              "type": "string"
            }
          },
          {
            "description": "Return this version of the gap instead of the current one.",
            "in": "query",
            "name": "version",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Return this version instead of the current one.",
              "title": "Version"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GapResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:read"
            ]
          }
        ],
        "summary": "Get a gap"
      },
      "patch": {
        "description": "Changes the gap's kind, detail, evidence, origin, tags or metadata and appends the next version. Send the version you read as `base_version`: a gap that has moved is a 409 `gap_moved` carrying the current version. Fields you omit are unchanged. A request that changes nothing, a change onto the words of another gap, or a change to a retired gap is refused.",
        "operationId": "patch_gap_v1_gaps__gap_id__patch",
        "parameters": [
          {
            "description": "The gap's id.",
            "in": "path",
            "name": "gap_id",
            "required": true,
            "schema": {
              "title": "Gap Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GapPatch"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GapResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:gaps"
            ]
          }
        ],
        "summary": "Change a gap"
      }
    },
    "/context/v1/gaps/{gap_id}/journal": {
      "get": {
        "description": "Returns every change to the gap, oldest first: the version it made, who made it, whether that was a person or an automation, and what changed. A retirement entry names the assets that cover the debt and the evidence behind it.",
        "operationId": "get_gap_journal_v1_gaps__gap_id__journal_get",
        "parameters": [
          {
            "description": "The gap's id.",
            "in": "path",
            "name": "gap_id",
            "required": true,
            "schema": {
              "title": "Gap Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GapJournalResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:read"
            ]
          }
        ],
        "summary": "Get a gap's journal"
      }
    },
    "/context/v1/gaps/{gap_id}/retire": {
      "post": {
        "description": "Closes the gap. `covered_by` is optional: it may name the assets that cover the debt (each must be an asset of the release the closure is recorded under, else a 422 naming it), and `rationale` is a free closing note shown with the closure so it can be judged and reverted. The release that closed it is recorded (`closed_release`, the latest when omitted). Every version stays readable. A kit that carries the gap is not changed: it skips the retired gap when served and drops the member later. A gap that has moved since `base_version` is a 409 `gap_moved`.",
        "operationId": "retire_gap_v1_gaps__gap_id__retire_post",
        "parameters": [
          {
            "description": "The gap's id.",
            "in": "path",
            "name": "gap_id",
            "required": true,
            "schema": {
              "title": "Gap Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GapRetire"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GapResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:gaps"
            ]
          }
        ],
        "summary": "Retire a gap"
      }
    },
    "/context/v1/gaps/{gap_id}/revert": {
      "post": {
        "description": "Appends a new version holding the definition of `to_version`. History is never rewritten: the revert is one more journal entry. Reverting a retired gap to a version from before its retirement reopens it. A gap that has moved since `base_version` is a 409 `gap_moved`.",
        "operationId": "revert_gap_v1_gaps__gap_id__revert_post",
        "parameters": [
          {
            "description": "The gap's id.",
            "in": "path",
            "name": "gap_id",
            "required": true,
            "schema": {
              "title": "Gap Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GapRevert"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GapResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:gaps"
            ]
          }
        ],
        "summary": "Revert a gap to an earlier version"
      }
    },
    "/context/v1/kits": {
      "get": {
        "description": "Returns the current version of every kit the project owns. A kit is a named, versioned selection of assets, such as skills, knowledge, tools and memories, that an agent is given for a kind of work; it is not itself an asset. Pass `release` or `tag` to see which members that state of the context can serve; the rest are listed as ignored with the reason.",
        "operationId": "list_kits_v1_kits_get",
        "parameters": [
          {
            "description": "Resolve the kit's assets as this release published them (a number). Omit, with no `tag`, for the latest release. Cannot be combined with `tag`.",
            "in": "query",
            "name": "release",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Resolve every kit's assets at this release number, or `latest` (the default).",
              "title": "Release"
            }
          },
          {
            "description": "Resolve the kit's assets as the release holding this tag published them. A tag no release holds is a 404. Cannot be combined with `release`.",
            "in": "query",
            "name": "tag",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Resolve every kit's assets at the release holding this tag.",
              "title": "Tag"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KitsResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:read"
            ]
          }
        ],
        "summary": "List kits"
      },
      "post": {
        "description": "Creates a kit at version 1, optionally with its first members. A kit is a named, versioned selection of assets an agent is given for a kind of work. It is not itself an asset: creating or changing one takes effect at once, needs no review and no release, and a release never changes a kit. Each member is an asset id; the role a kit holds it in follows from the asset's type, and an omitted rank appends. An asset that does not exist, or a kit named as a member, is a 422.",
        "operationId": "create_kit_v1_kits_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KitCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KitResponse"
                }
              }
            },
            "description": "OK"
          },
          "201": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:kits"
            ]
          }
        ],
        "summary": "Create a kit"
      }
    },
    "/context/v1/kits/{kit_id}": {
      "delete": {
        "description": "Retires the kit. Every version stays readable and the retirement is one more entry in the kit's journal. A kit that has moved since `base_version` is a 409 `kit_moved`.",
        "operationId": "retire_kit_v1_kits__kit_id__delete",
        "parameters": [
          {
            "description": "The kit's id.",
            "in": "path",
            "name": "kit_id",
            "required": true,
            "schema": {
              "title": "Kit Id",
              "type": "string"
            }
          },
          {
            "description": "The kit version you read.",
            "in": "query",
            "name": "base_version",
            "required": true,
            "schema": {
              "description": "The kit version you read.",
              "title": "Base Version",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:kits"
            ]
          }
        ],
        "summary": "Retire a kit"
      },
      "get": {
        "description": "Returns one kit at its current version, or at the version given in `version`. Pass `release` or `tag` to see which members that state of the context can serve; the rest are listed as ignored with the reason.",
        "operationId": "get_kit_v1_kits__kit_id__get",
        "parameters": [
          {
            "description": "The kit's id.",
            "in": "path",
            "name": "kit_id",
            "required": true,
            "schema": {
              "title": "Kit Id",
              "type": "string"
            }
          },
          {
            "description": "Return this version of the kit instead of the current one.",
            "in": "query",
            "name": "version",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "description": "The kit's own version; the current one when omitted.",
              "title": "Version"
            }
          },
          {
            "description": "Resolve the kit's assets as this release published them (a number). Omit, with no `tag`, for the latest release. Cannot be combined with `tag`.",
            "in": "query",
            "name": "release",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Resolve the kit's assets at this release number, or `latest` (the default).",
              "title": "Release"
            }
          },
          {
            "description": "Resolve the kit's assets as the release holding this tag published them. A tag no release holds is a 404. Cannot be combined with `release`.",
            "in": "query",
            "name": "tag",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Resolve the kit's assets at the release holding this tag.",
              "title": "Tag"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KitResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:read"
            ]
          }
        ],
        "summary": "Get a kit"
      },
      "patch": {
        "description": "Changes the kit's title, description, tags, metadata or `auto_maintain` flag, and appends the next kit version. Send the version you read as `base_version`: if the kit has moved since, nothing is written and the answer is a 409 `kit_moved` carrying the current version. Fields you omit are unchanged. A request that changes nothing is refused.",
        "operationId": "patch_kit_v1_kits__kit_id__patch",
        "parameters": [
          {
            "description": "The kit's id.",
            "in": "path",
            "name": "kit_id",
            "required": true,
            "schema": {
              "title": "Kit Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KitPatch"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KitResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:kits"
            ]
          }
        ],
        "summary": "Change a kit's own fields"
      }
    },
    "/context/v1/kits/{kit_id}/changelog": {
      "get": {
        "description": "Returns what changed in a kit over its history, including changes to the assets it holds: a summary with one entry per kit version, and the revisions behind it, newest first.",
        "operationId": "get_kit_changelog_v1_kits__kit_id__changelog_get",
        "parameters": [
          {
            "description": "The kit's id.",
            "in": "path",
            "name": "kit_id",
            "required": true,
            "schema": {
              "title": "Kit Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KitChangelogResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:read"
            ]
          }
        ],
        "summary": "Get a kit's changelog"
      }
    },
    "/context/v1/kits/{kit_id}/export": {
      "get": {
        "description": "Returns the kit and the skills it holds as a ZIP archive, packaged as an agent plugin that can be installed elsewhere. The response is a file, not JSON. Pass `version` to export an earlier version of the kit.",
        "operationId": "export_kit_v1_kits__kit_id__export_get",
        "parameters": [
          {
            "description": "The kit's id.",
            "in": "path",
            "name": "kit_id",
            "required": true,
            "schema": {
              "title": "Kit Id",
              "type": "string"
            }
          },
          {
            "description": "Export this version of the kit instead of the current one.",
            "in": "query",
            "name": "version",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Version"
            }
          },
          {
            "description": "Resolve the kit's assets as this release published them (a number). Omit, with no `tag`, for the latest release. Cannot be combined with `tag`.",
            "in": "query",
            "name": "release",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Read the kit's assets at this release number, or `latest` (the default).",
              "title": "Release"
            }
          },
          {
            "description": "Resolve the kit's assets as the release holding this tag published them. A tag no release holds is a 404. Cannot be combined with `release`.",
            "in": "query",
            "name": "tag",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Read the kit's assets at the release holding this tag.",
              "title": "Tag"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/zip": {
                "schema": {
                  "format": "binary",
                  "type": "string"
                }
              }
            },
            "description": "The kit as a ZIP archive."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:read"
            ]
          }
        ],
        "summary": "Export a kit"
      }
    },
    "/context/v1/kits/{kit_id}/full": {
      "get": {
        "description": "Returns one kit together with the body of every asset it holds, grouped by type, in one call. Pass `release` or `tag` to read the assets as a release published them; the kit's own members are always the version named by `version`, or the current one. An unknown release is a 404.",
        "operationId": "get_full_kit_v1_kits__kit_id__full_get",
        "parameters": [
          {
            "description": "The kit's id.",
            "in": "path",
            "name": "kit_id",
            "required": true,
            "schema": {
              "title": "Kit Id",
              "type": "string"
            }
          },
          {
            "description": "Read this version of the kit instead of the current one.",
            "in": "query",
            "name": "version",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "description": "The kit's own version; the current one when omitted.",
              "title": "Version"
            }
          },
          {
            "description": "Read the kit's assets as this release published them. Omit for the latest state.",
            "in": "query",
            "name": "release",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Pin every inlined asset's body to this release, or `latest` for the project's newest published release. Omit for live. Unknown release -> 404, the same exact-lookup contract `GET /v1/assets?release=N` and `GET /v1/graph?release=N` keep.",
              "title": "Release"
            }
          },
          {
            "description": "Resolve the kit's assets as the release holding this tag published them. A tag no release holds is a 404. Cannot be combined with `release`.",
            "in": "query",
            "name": "tag",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Pin to the release holding this tag.",
              "title": "Tag"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KitFullResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:read"
            ]
          }
        ],
        "summary": "Get a kit with its assets"
      }
    },
    "/context/v1/kits/{kit_id}/journal": {
      "get": {
        "description": "Returns every change to the kit itself, oldest first: the version it made, who made it, whether that was a person or an automation, and what changed. Unlike the changelog it does not include changes to the assets the kit holds.",
        "operationId": "get_kit_journal_v1_kits__kit_id__journal_get",
        "parameters": [
          {
            "description": "The kit's id.",
            "in": "path",
            "name": "kit_id",
            "required": true,
            "schema": {
              "title": "Kit Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KitJournalResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:read"
            ]
          }
        ],
        "summary": "Get a kit's journal"
      }
    },
    "/context/v1/kits/{kit_id}/members": {
      "post": {
        "description": "Adds assets of any type to the kit and appends the next kit version. The role follows from each asset's type; an omitted rank appends after the kit's last member of that role. Send the version you read as `base_version`: a kit that has moved is a 409 `kit_moved`. An asset already in the kit, one that does not exist, or a kit is refused.",
        "operationId": "add_kit_members_v1_kits__kit_id__members_post",
        "parameters": [
          {
            "description": "The kit's id.",
            "in": "path",
            "name": "kit_id",
            "required": true,
            "schema": {
              "title": "Kit Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KitAddMembers"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KitResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:kits"
            ]
          }
        ],
        "summary": "Add assets to a kit"
      }
    },
    "/context/v1/kits/{kit_id}/members/{asset_id}": {
      "delete": {
        "description": "Removes one asset from the kit and appends the next kit version. Works for an asset a release has since retired, which is how a kit stops naming it. The asset itself is untouched. A kit that has moved since `base_version` is a 409 `kit_moved`; an asset the kit does not hold is refused.",
        "operationId": "remove_kit_member_v1_kits__kit_id__members__asset_id__delete",
        "parameters": [
          {
            "description": "The kit's id.",
            "in": "path",
            "name": "kit_id",
            "required": true,
            "schema": {
              "title": "Kit Id",
              "type": "string"
            }
          },
          {
            "description": "The asset to take out of the kit.",
            "in": "path",
            "name": "asset_id",
            "required": true,
            "schema": {
              "title": "Asset Id",
              "type": "string"
            }
          },
          {
            "description": "The kit version you read.",
            "in": "query",
            "name": "base_version",
            "required": true,
            "schema": {
              "description": "The kit version you read.",
              "title": "Base Version",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KitResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:kits"
            ]
          }
        ],
        "summary": "Remove an asset from a kit"
      }
    },
    "/context/v1/kits/{kit_id}/revert": {
      "post": {
        "description": "Appends a new kit version holding the fields and members of `to_version`. History is never rewritten: the revert is one more entry in the kit's journal. A kit that has moved since `base_version` is a 409 `kit_moved`.",
        "operationId": "revert_kit_v1_kits__kit_id__revert_post",
        "parameters": [
          {
            "description": "The kit's id.",
            "in": "path",
            "name": "kit_id",
            "required": true,
            "schema": {
              "title": "Kit Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KitRevert"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KitResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:kits"
            ]
          }
        ],
        "summary": "Revert a kit to an earlier version"
      }
    },
    "/context/v1/project": {
      "get": {
        "description": "Returns the identity of the project the calling key resolves to: its id and the environment that serves it. Call it before writing to confirm the key points at the project you intend. It takes no parameters and returns nothing about any other project.",
        "operationId": "get_project_identity_v1_project_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectIdentity"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:read"
            ]
          }
        ],
        "summary": "Get the project this key belongs to"
      }
    },
    "/context/v1/releases": {
      "get": {
        "description": "Returns the project's release history, newest first. A release is one published state of the whole context repository; each published change creates the next. Pass `release` to read one release by number, or `tag` to read the release currently holding that tag; the two cannot be combined, and a tag no release holds is a 404. The response also reports which release is the latest.",
        "operationId": "list_releases_v1_releases_get",
        "parameters": [
          {
            "description": "Return at most this many releases, from 1 to 200. Defaults to 50.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 50,
              "maximum": 200,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "description": "Skip this many releases before returning. Defaults to 0.",
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "default": 0,
              "minimum": 0,
              "title": "Offset",
              "type": "integer"
            }
          },
          {
            "description": "Return the release currently holding this tag. A tag no release holds is a 404. Cannot be combined with `release`.",
            "in": "query",
            "name": "tag",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Tag"
            }
          },
          {
            "description": "Return this one release, by number or canonical name (`projects/{project}/releases/{n}`). Cannot be combined with `tag`.",
            "in": "query",
            "name": "release",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "A release number or a release's canonical name (`projects/{project}/releases/{n}`).",
              "title": "Release"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReleasesResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:read"
            ]
          }
        ],
        "summary": "List releases"
      }
    },
    "/context/v1/releases/{release}": {
      "get": {
        "description": "Returns one release: when it was made, by whom, which changeset made it, the version of every object it published and the tags it carries. An unknown release is a 404.",
        "operationId": "get_release_route_v1_releases__release__get",
        "parameters": [
          {
            "description": "The release number.",
            "in": "path",
            "name": "release",
            "required": true,
            "schema": {
              "title": "Release",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReleaseRecord"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:read"
            ]
          }
        ],
        "summary": "Get a release"
      }
    },
    "/context/v1/releases/{release}/tags": {
      "put": {
        "description": "Sets the complete tag list of a published release. A tag names one release at a time, so setting a tag here moves it off whichever release held it, and every reader of that tag is then served this release. It changes no release number and no object version.",
        "operationId": "replace_release_tags_route_v1_releases__release__tags_put",
        "parameters": [
          {
            "description": "The release number.",
            "in": "path",
            "name": "release",
            "required": true,
            "schema": {
              "title": "Release",
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "tags": [
                  "production"
                ]
              },
              "schema": {
                "$ref": "#/components/schemas/ReplaceTagsRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReleaseRecord"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:assets"
            ]
          }
        ],
        "summary": "Replace a release's tags"
      }
    },
    "/context/v1/releases/{release}/tags/{tag}": {
      "delete": {
        "description": "Removes one tag from a published release. Safe to repeat. It changes no release number and no object version.",
        "operationId": "remove_release_tag_route_v1_releases__release__tags__tag__delete",
        "parameters": [
          {
            "description": "The release number.",
            "in": "path",
            "name": "release",
            "required": true,
            "schema": {
              "title": "Release",
              "type": "integer"
            }
          },
          {
            "description": "The tag to remove.",
            "in": "path",
            "name": "tag",
            "required": true,
            "schema": {
              "title": "Tag",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReleaseRecord"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:assets"
            ]
          }
        ],
        "summary": "Remove a tag from a release"
      },
      "post": {
        "description": "Adds one tag to a published release, moving it off whichever release held it before. Safe to repeat. It changes no release number and no object version.",
        "operationId": "add_release_tag_route_v1_releases__release__tags__tag__post",
        "parameters": [
          {
            "description": "The release number.",
            "in": "path",
            "name": "release",
            "required": true,
            "schema": {
              "title": "Release",
              "type": "integer"
            }
          },
          {
            "description": "The tag to add.",
            "in": "path",
            "name": "tag",
            "required": true,
            "schema": {
              "title": "Tag",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReleaseRecord"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:assets"
            ]
          }
        ],
        "summary": "Add a tag to a release"
      }
    },
    "/context/v1/search": {
      "post": {
        "description": "Finds assets for a query by text match, best first. It never calls a model, so it is fast and has no per-call cost beyond the request itself. Restrict the types searched with `asset_type`. Send `queries` instead of `query` to run up to 20 independent searches, answered in the same order. An unknown asset type is a 400.",
        "operationId": "search_route_v1_search_post",
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "asset_type": [
                  "knowledge_page"
                ],
                "max_results": 5,
                "query": "refund policy"
              },
              "schema": {
                "$ref": "#/components/schemas/SearchRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResponse"
                }
              }
            },
            "description": "The request succeeded."
          },
          "401": {
            "description": "The token is missing, expired or invalid."
          },
          "403": {
            "description": "The token does not carry the scope this operation requires."
          },
          "404": {
            "description": "No such project, or the token belongs to a different project."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "The request was not valid: a parameter or the body failed validation."
          }
        },
        "security": [
          {
            "customerToken": [
              "context:read"
            ]
          }
        ],
        "summary": "Search the project's context"
      }
    }
  },
  "servers": [
    {
      "description": "Staging",
      "url": "https://api.staging.coelevate.ai"
    },
    {
      "description": "Demo",
      "url": "https://api.demo.coelevate.ai"
    }
  ]
}
