{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://echo.cc/schemas/result-v1.json",
  "title": "echo.cc v1 terminal result",
  "description": "One attempt's terminal result, shared by CLI and API workers. The runtime writes every field except summary and detail, which come from the worker's validated payload ($defs.payload, the schema sent to providers). Structural validation only: echo also enforces byte limits, control characters, one-line fields and timing order. JSON parsing must reject duplicate keys and wrong-case field names.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "schema",
    "id",
    "worker",
    "kind",
    "task",
    "fence",
    "attempt",
    "status",
    "started",
    "finished"
  ],
  "properties": {
    "schema": {
      "const": "https://echo.cc/schemas/result-v1.json"
    },
    "id": {
      "$ref": "#/$defs/ulid"
    },
    "worker": {
      "$ref": "#/$defs/member"
    },
    "kind": {
      "enum": [
        "cli",
        "api"
      ]
    },
    "task": {
      "$ref": "#/$defs/ulid"
    },
    "fence": {
      "type": "integer",
      "minimum": 1
    },
    "attempt": {
      "$ref": "#/$defs/ulid",
      "description": "The run this result ends: the ID of the claim that started it. A resume keeps the fence but is a new run, and echod accepts a result only for the task's current run."
    },
    "status": {
      "enum": [
        "completed",
        "refused",
        "incomplete",
        "cancelled",
        "timed_out",
        "provider_error",
        "invalid_output"
      ]
    },
    "summary": {
      "type": "string",
      "minLength": 1,
      "maxLength": 160
    },
    "detail": {
      "type": "string",
      "maxLength": 65536
    },
    "checks": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/check"
      }
    },
    "model": {
      "$ref": "#/$defs/model"
    },
    "usage": {
      "$ref": "#/$defs/usage"
    },
    "error": {
      "$ref": "#/$defs/error"
    },
    "started": {
      "$ref": "#/$defs/timestamp"
    },
    "finished": {
      "$ref": "#/$defs/timestamp"
    }
  },
  "allOf": [
    {
      "if": {
        "properties": {
          "status": {
            "const": "completed"
          }
        }
      },
      "then": {
        "required": [
          "checks"
        ],
        "properties": {
          "checks": {
            "minItems": 1,
            "items": {
              "properties": {
                "exit": {
                  "const": 0
                }
              }
            }
          }
        },
        "not": {
          "required": [
            "error"
          ]
        }
      },
      "else": {
        "required": [
          "error"
        ]
      }
    },
    {
      "if": {
        "properties": {
          "kind": {
            "const": "api"
          }
        }
      },
      "then": {
        "required": [
          "model"
        ]
      },
      "else": {
        "not": {
          "anyOf": [
            {
              "required": [
                "model"
              ]
            },
            {
              "required": [
                "usage"
              ]
            }
          ]
        }
      }
    }
  ],
  "$defs": {
    "ulid": {
      "type": "string",
      "pattern": "^[0-7][0-9A-HJKMNP-TV-Z]{25}$"
    },
    "member": {
      "type": "string",
      "pattern": "^[a-z0-9][a-z0-9-]{0,62}\\.[a-z0-9][a-z0-9-]{0,62}\\.[a-z0-9][a-z0-9-]{0,62}$"
    },
    "timestamp": {
      "type": "string",
      "format": "date-time"
    },
    "check": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "command",
        "exit"
      ],
      "properties": {
        "command": {
          "type": "string",
          "minLength": 1,
          "maxLength": 1024
        },
        "exit": {
          "type": "integer"
        },
        "output": {
          "type": "string",
          "maxLength": 4096
        },
        "repo": {
          "type": "string"
        },
        "sha": {
          "type": "string"
        }
      }
    },
    "model": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "provider",
        "requested"
      ],
      "properties": {
        "provider": {
          "type": "string",
          "pattern": "^[a-z0-9][a-z0-9-]{0,62}$"
        },
        "requested": {
          "type": "string",
          "minLength": 1
        },
        "observed": {
          "type": "string"
        },
        "finish": {
          "type": "string"
        }
      }
    },
    "usage": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "input_tokens",
        "output_tokens"
      ],
      "properties": {
        "input_tokens": {
          "type": "integer",
          "minimum": 0
        },
        "output_tokens": {
          "type": "integer",
          "minimum": 0
        }
      }
    },
    "error": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "code",
        "message"
      ],
      "properties": {
        "code": {
          "type": "string",
          "pattern": "^[a-z][a-z0-9_]{0,62}$"
        },
        "message": {
          "type": "string",
          "maxLength": 512
        }
      }
    },
    "payload": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "status",
        "summary",
        "detail"
      ],
      "properties": {
        "status": {
          "type": "string",
          "enum": [
            "completed",
            "refused"
          ]
        },
        "summary": {
          "type": "string",
          "description": "one line, at most 160 characters"
        },
        "detail": {
          "type": "string"
        }
      }
    }
  }
}
