{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://local/harness/events.schema.json",
  "title": "Normalized harness events",
  "description": "Stateless per-line normalization target for claude/cursor/codex stream records.",
  "type": "object",
  "additionalProperties": true,
  "required": [
    "v",
    "seq",
    "position",
    "dialect",
    "kind",
    "subtype",
    "raw",
    "parsed"
  ],
  "properties": {
    "v": { "const": "events/v1" },
    "seq": { "type": "integer", "minimum": 0 },
    "position": { "type": "integer", "minimum": 0 },
    "dialect": {
      "type": "string",
      "enum": ["claude", "cursor", "codex", "north", "pi", "grok", "canary", "opencode", "solweb"]
    },
    "kind": {
      "type": "string",
      "enum": ["message", "tool_call", "status", "error", "usage"]
    },
    "subtype": { "type": "string", "minLength": 1 },
    "role": { "type": "string" },
    "text": { "type": "string" },
    "tool": {
      "type": "object",
      "additionalProperties": true,
      "required": ["name"],
      "properties": {
        "name": { "type": "string", "minLength": 1 },
        "arguments": {}
      }
    },
    "error": {
      "type": "object",
      "additionalProperties": false,
      "required": ["code", "message"],
      "properties": {
        "code": { "type": "string", "minLength": 1 },
        "message": { "type": "string", "minLength": 1 },
        "errorKind": {
          "type": "string",
          "enum": ["quota", "transport", "semantic"]
        }
      }
    },
    "usage": {
      "type": "object",
      "additionalProperties": false,
      "required": ["model"],
      "properties": {
        "inputTokens": { "type": "number", "minimum": 0 },
        "outputTokens": { "type": "number", "minimum": 0 },
        "cachedTokens": { "type": "number", "minimum": 0 },
        "costUsd": { "type": "number", "minimum": 0 },
        "model": { "type": "string", "minLength": 1 },
        "unknown": { "type": "boolean" }
      },
      "oneOf": [
        {
          "required": ["inputTokens", "outputTokens"]
        },
        {
          "required": ["unknown"],
          "properties": {
            "unknown": { "const": true }
          }
        }
      ]
    },
    "raw": { "type": "string" },
    "parsed": {}
  },
  "allOf": [
    {
      "if": {
        "properties": { "kind": { "const": "error" } },
        "required": ["kind"]
      },
      "then": {
        "required": ["error"]
      }
    },
    {
      "if": {
        "properties": { "kind": { "const": "message" } },
        "required": ["kind"]
      },
      "then": {
        "required": ["text"]
      }
    },
    {
      "if": {
        "properties": { "kind": { "const": "tool_call" } },
        "required": ["kind"]
      },
      "then": {
        "required": ["tool"]
      }
    },
    {
      "if": {
        "properties": { "kind": { "const": "usage" } },
        "required": ["kind"]
      },
      "then": {
        "required": ["usage"]
      }
    }
  ]
  ,
  "$defs": {
    "gateFailClass": {
      "type": "string",
      "enum": ["build", "typecheck", "lint", "test", "timeout", "other"]
    },
    "attemptStarted": {
      "type": "object",
      "additionalProperties": true,
      "required": ["task", "phase", "ordinal", "attemptId", "leaseId", "processGeneration"],
      "properties": {
        "kind": { "const": "attempt.started" },
        "task": { "type": "string" },
        "phase": { "type": "string", "enum": ["implement", "review", "fix"] },
        "ordinal": { "type": "integer", "minimum": 1 },
        "attemptId": { "type": "string", "minLength": 1 },
        "leaseId": { "type": "string", "minLength": 1 },
        "processGeneration": { "type": "integer", "minimum": 1 }
      }
    },
    "gate0Fail": {
      "type": "object",
      "additionalProperties": true,
      "required": ["task", "message"],
      "properties": {
        "kind": { "const": "gate0.fail" },
        "task": { "type": "string" },
        "message": { "type": "string" },
        "failClass": { "$ref": "#/$defs/gateFailClass" },
        "command": {
          "type": "array",
          "items": { "type": "string" }
        },
        "cwd": { "type": "string" },
        "attemptId": { "type": "string" }
      }
    },
    "provisionFailed": {
      "type": "object",
      "additionalProperties": true,
      "required": ["taskId", "cmd", "exitCode", "logTail"],
      "properties": {
        "kind": { "const": "provision.failed" },
        "taskId": { "type": "string", "minLength": 1 },
        "cmd": { "type": ["string", "null"] },
        "exitCode": { "type": "integer" },
        "logTail": { "type": ["string", "null"] }
      }
    },
    "reviewComplete": {
      "type": "object",
      "additionalProperties": true,
      "required": ["verdict"],
      "properties": {
        "kind": { "const": "review.complete" },
        "verdict": { "type": "string", "enum": ["pass", "fail", "changes-requested"] },
        "findings": {
          "type": "array",
          "items": {
            "type": "object",
            "required": ["severity", "message"],
            "properties": {
              "severity": { "type": "string", "enum": ["blocker", "major", "minor"] },
              "message": { "type": "string" },
              "file": { "type": "string" },
              "line": { "type": "number" }
            }
          }
        },
        "attemptId": { "type": "string" }
      }
    },
    "taskDuration": {
      "type": "object",
      "additionalProperties": true,
      "required": ["task", "phase", "durationMs"],
      "properties": {
        "kind": { "const": "task.duration" },
        "task": { "type": "string" },
        "phase": { "type": "string" },
        "durationMs": { "type": "number", "minimum": 1 },
        "attemptId": { "type": "string" }
      }
    },
    "taskDiff": {
      "type": "object",
      "additionalProperties": true,
      "required": ["task", "filesTouched", "insertions", "deletions"],
      "properties": {
        "kind": { "const": "task.diff" },
        "task": { "type": "string" },
        "filesTouched": {
          "type": "array",
          "items": { "type": "string" }
        },
        "insertions": { "type": "number", "minimum": 0 },
        "deletions": { "type": "number", "minimum": 0 },
        "attemptId": { "type": "string" }
      }
    },
    "acceptanceResult": {
      "type": "object",
      "additionalProperties": true,
      "required": ["task", "criterionId", "result"],
      "properties": {
        "kind": { "const": "acceptance.result" },
        "task": { "type": "string" },
        "criterionId": { "type": "string" },
        "result": { "type": "string", "enum": ["pass", "fail", "pending"] },
        "evidenceRef": { "type": "string" }
      }
    },
    "runStart": {
      "type": "object",
      "additionalProperties": true,
      "required": ["engineSha", "engineVersion", "engineRoot"],
      "properties": {
        "kind": { "const": "run.start" },
        "engineSha": { "type": "string", "minLength": 1 },
        "engineVersion": { "type": "string", "minLength": 1 },
        "engineRoot": { "type": "string", "minLength": 1 },
        "engineDirty": { "type": "boolean" }
      }
    },
    "qualityEvent": {
      "type": "object",
      "additionalProperties": true,
      "required": ["kind", "task", "phase", "binding", "baseHead", "taskHead"],
      "properties": {
        "kind": { "type": "string" },
        "task": { "type": "string", "minLength": 1 },
        "phase": { "type": "string", "minLength": 1 },
        "binding": { "type": "string", "minLength": 1 },
        "baseHead": { "type": "string", "minLength": 1 },
        "taskHead": { "type": "string", "minLength": 1 },
        "failureClass": { "type": "string", "minLength": 1 },
        "failureFingerprint": { "type": "string", "minLength": 1 }
      }
    },
    "reviewAttempt": {
      "allOf": [
        { "$ref": "#/$defs/qualityEvent" },
        { "properties": { "kind": { "const": "review.attempt" } } }
      ]
    },
    "reviewVerdict": {
      "allOf": [
        { "$ref": "#/$defs/qualityEvent" },
        {
          "required": ["verdict"],
          "properties": {
            "kind": { "const": "review.verdict" },
            "verdict": { "type": "string", "enum": ["pass", "fail", "changes-requested"] }
          }
        }
      ]
    },
    "fixRung": {
      "allOf": [
        { "$ref": "#/$defs/qualityEvent" },
        {
          "required": ["rung"],
          "properties": {
            "kind": { "const": "fix.rung" },
            "rung": { "type": "string", "enum": ["dependency-repair", "fixer", "stronger-fixer"] }
          }
        }
      ]
    },
    "bindingFallbackAttempt": {
      "allOf": [
        { "$ref": "#/$defs/qualityEvent" },
        { "properties": { "kind": { "const": "binding.fallback.attempt" } } }
      ]
    },
    "retryAttempt": {
      "allOf": [
        { "$ref": "#/$defs/qualityEvent" },
        {
          "required": ["failureClass", "failureFingerprint", "outcome"],
          "properties": {
            "kind": { "const": "retry.attempt" },
            "outcome": { "type": "string", "enum": ["failed", "succeeded"] }
          }
        }
      ]
    },
    "rateLimitPark": {
      "allOf": [
        { "$ref": "#/$defs/qualityEvent" },
        {
          "required": ["failureClass", "failureFingerprint", "parkCount", "resetAt"],
          "properties": {
            "kind": { "const": "rate-limit.parked" },
            "parkCount": { "type": "integer", "minimum": 1 },
            "resetAt": { "type": "string", "format": "date-time" }
          }
        }
      ]
    },
    "rateLimitHeartbeat": {
      "allOf": [
        { "$ref": "#/$defs/qualityEvent" },
        { "properties": { "kind": { "const": "rate-limit.heartbeat" } } }
      ]
    },
    "rateLimitWake": {
      "allOf": [
        { "$ref": "#/$defs/qualityEvent" },
        { "properties": { "kind": { "const": "rate-limit.woken" } } }
      ]
    },
    "quarantine": {
      "allOf": [
        { "$ref": "#/$defs/qualityEvent" },
        { "properties": { "kind": { "const": "quarantine" } } }
      ]
    },
    "stopLoss": {
      "allOf": [
        { "$ref": "#/$defs/qualityEvent" },
        {
          "required": ["failureClass", "failureFingerprint"],
          "properties": { "kind": { "const": "retry.stop-loss" } }
        }
      ]
    },
    "engineMigrated": {
      "type": "object",
      "additionalProperties": true,
      "required": ["fromSha", "toSha"],
      "properties": {
        "kind": { "const": "engine.migrated" },
        "fromSha": { "type": "string", "minLength": 1 },
        "toSha": { "type": "string", "minLength": 1 }
      }
    },
    "supervisionOwnership": {
      "type": "object",
      "additionalProperties": false,
      "required": ["pid", "startTime", "processGroup", "cgroup", "generation"],
      "properties": {
        "pid": { "type": "integer", "minimum": 1 },
        "startTime": { "type": "string", "pattern": "^[0-9]+$" },
        "processGroup": { "type": "integer", "minimum": 1 },
        "cgroup": { "type": "string", "minLength": 1 },
        "generation": { "type": "integer", "minimum": 1 }
      }
    },
    "supervisionRegistered": {
      "type": "object",
      "additionalProperties": true,
      "required": ["kind", "generation", "token", "unit"],
      "properties": {
        "kind": { "const": "supervision.registered" },
        "generation": { "type": "integer", "minimum": 1 },
        "token": { "type": "string", "pattern": "^[A-Za-z0-9._-]{1,128}$" },
        "unit": { "type": "string", "pattern": "^harness-run@[A-Za-z0-9._-]{1,128}\\.service$" }
      }
    },
    "queueLaunch": {
      "type": "object",
      "additionalProperties": true,
      "required": ["kind", "queueId", "attempt", "token"],
      "properties": {
        "kind": { "const": "queue.launch" },
        "queueId": { "type": "string", "minLength": 1 },
        "attempt": { "type": "integer", "minimum": 1 },
        "token": { "type": "string", "pattern": "^[A-Za-z0-9._-]{1,128}$" }
      }
    },
    "queueWindowBypassed": {
      "type": "object",
      "additionalProperties": true,
      "required": ["kind", "requestedAt"],
      "properties": {
        "kind": { "const": "queue.window-bypassed" },
        "requestedAt": { "type": "string", "format": "date-time" }
      }
    },
    "supervisionHeartbeat": {
      "type": "object",
      "additionalProperties": true,
      "required": ["kind", "generation", "heartbeatAt"],
      "properties": {
        "kind": { "const": "supervision.heartbeat" },
        "generation": { "type": "integer", "minimum": 1 },
        "heartbeatAt": { "type": "integer", "minimum": 0 }
      }
    },
    "supervisionCrashed": {
      "type": "object",
      "additionalProperties": true,
      "required": ["kind", "generation", "coordinator"],
      "properties": {
        "kind": { "const": "supervision.crashed" },
        "generation": { "type": "integer", "minimum": 1 },
        "coordinator": { "$ref": "#/$defs/supervisionOwnership" }
      }
    },
    "supervisionRestartScheduled": {
      "type": "object",
      "additionalProperties": true,
      "required": ["kind", "generation", "delayMs", "nextRestartAt"],
      "properties": {
        "kind": { "const": "supervision.restart-scheduled" },
        "generation": { "type": "integer", "minimum": 1 },
        "delayMs": { "type": "integer", "enum": [30000, 120000, 480000] },
        "nextRestartAt": { "type": "integer", "minimum": 0 }
      }
    },
    "supervisionRestartRefused": {
      "type": "object",
      "additionalProperties": true,
      "required": ["kind", "generation"],
      "properties": {
        "kind": { "const": "supervision.restart-refused" },
        "generation": { "type": "integer", "minimum": 1 }
      }
    },
    "attemptOwnership": {
      "type": "object",
      "additionalProperties": true,
      "required": ["kind", "generation", "ownership"],
      "properties": {
        "kind": { "const": "attempt.ownership" },
        "generation": { "type": "integer", "minimum": 1 },
        "ownership": { "$ref": "#/$defs/supervisionOwnership" }
      }
    },
    "watchdogIncident": {
      "type": "object",
      "additionalProperties": true,
      "required": ["kind", "generation", "reason"],
      "properties": {
        "kind": { "const": "watchdog.incident" },
        "generation": { "type": "integer", "minimum": 1 },
        "reason": { "type": "string", "minLength": 1 }
      }
    },
    "resourceLimit": {
      "type": "object",
      "additionalProperties": true,
      "required": ["kind", "generation", "limit", "unit"],
      "properties": {
        "kind": { "const": "resource.limit" },
        "generation": { "type": "integer", "minimum": 1 },
        "limit": { "type": "string", "enum": ["memory", "cpu", "process", "file-size"] },
        "unit": { "type": "string", "minLength": 1 }
      }
    }
  }
}
