{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "v": {
      "type": "number",
      "const": 1,
      "description": "Protocol major version."
    },
    "type": {
      "type": "string",
      "const": "run.started"
    },
    "id": {
      "type": "string",
      "pattern": "^evt_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
      "description": "The event's own id. Stable across a retry of the same event."
    },
    "ts": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
      "description": "When it happened, by Chips' clock. Stamped on the way in; a value the sender writes is replaced."
    },
    "workspace_id": {
      "type": "string",
      "pattern": "^ws_[0-7][0-9A-HJKMNP-TV-Z]{25}$",
      "description": "A workspace identifier: `ws_` followed by a ULID."
    },
    "space_id": {
      "description": "The space, when the event belongs to one.",
      "type": "string",
      "pattern": "^spc_[0-7][0-9A-HJKMNP-TV-Z]{25}$"
    },
    "run_id": {
      "description": "The run, when the event belongs to one.",
      "type": "string",
      "pattern": "^run_[0-7][0-9A-HJKMNP-TV-Z]{25}$"
    },
    "seq": {
      "description": "Assigned by the server on append, monotonic per workspace. Absent on the way in.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "idempotency_key": {
      "description": "Required on every client-originated write. Sending the same key twice is a no-op.",
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    },
    "actor": {
      "type": "object",
      "properties": {
        "kind": {
          "type": "string",
          "enum": [
            "person",
            "harness",
            "agent",
            "system"
          ],
          "description": "Whether a person, a harness, one of a harness's agents or Chips itself acted."
        },
        "id": {
          "type": "string",
          "minLength": 1,
          "description": "The participant id, or `system` for Chips."
        },
        "harness_id": {
          "description": "For an agent: the harness it speaks through, whose budget and runs are the agent's (ADR 0087). Filled in by Chips.",
          "type": "string",
          "pattern": "^hrn_[0-7][0-9A-HJKMNP-TV-Z]{25}$"
        }
      },
      "required": [
        "kind",
        "id"
      ],
      "description": "The participant an event is attributed to."
    },
    "goal": {
      "type": "string",
      "minLength": 1,
      "maxLength": 4000,
      "description": "What the run is for, in the person's words where possible."
    },
    "plan": {
      "description": "The steps the harness expects to take. The run panel draws one hollow dot each.",
      "maxItems": 64,
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "step_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120,
            "description": "Stable for the life of the run, so updates land on the right row."
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 300,
            "description": "What this step will do."
          }
        },
        "required": [
          "step_id",
          "title"
        ],
        "description": "One step of a plan, shown as a hollow dot until it completes."
      }
    },
    "session_ref": {
      "description": "The visit this run belongs to, so two terminals in one space are told apart.",
      "type": "string",
      "minLength": 1,
      "maxLength": 500
    },
    "goal_from": {
      "description": "Where the goal came from. `harness`: a person asked for it at the harness's own surface — a terminal, a chat the harness already had — so Chips shows it as their message, because otherwise the room holds only the answers. `chips`: it arrived as a message here and is already on screen. Either way the room's header and the run panel leave the goal out, because the room shows it. Omit when the goal was not a person's words at all; the header and the run panel then say it.",
      "type": "string",
      "enum": [
        "harness",
        "chips"
      ]
    }
  },
  "required": [
    "v",
    "type",
    "id",
    "ts",
    "workspace_id",
    "actor",
    "goal"
  ],
  "description": "A harness has begun a unit of work, optionally with the plan it intends to follow.",
  "$id": "https://chipschat.ai/schema/v1/run.started.json",
  "title": "RunStarted"
}
