{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://law.arxo.io/schema/inspection.schema.json",
  "title": "Arxo inspection 0.1", "$comment": "DECISION-0449",
  "description": "A read-only view over an already computed evaluation document and its pinned run context. It computes nothing, enters no hashes, and issues no new semantic verdicts; missing data is a limit state of the explanation, never a denial.",
  "oneOf": [
    {
      "$ref": "#/$defs/Request"
    },
    {
      "$ref": "#/$defs/Answer"
    },
    {
      "$ref": "#/$defs/RequestError"
    },
    {
      "$ref": "#/$defs/Bundle"
    }
  ],
  "$defs": {
    "Schema": {
      "const": "law.inspection/0.1"
    },
    "Operation": {
      "enum": [
        "summary",
        "slice",
        "diff",
        "locate"
      ]
    },
    "LimitState": {
      "description": "The seven limit states of an explanation.", "$comment": "DECISION-0449; SPEC §3.4",
      "enum": [
        "no_evidence",
        "not_asked",
        "unsupported",
        "truncated",
        "evaluation_failed",
        "source_unavailable",
        "hash_mismatch"
      ]
    },
    "VerificationState": {
      "enum": [
        "verified",
        "mismatch",
        "unavailable"
      ]
    },
    "EvaluationDocument": {
      "description": "An evaluation document in either evaluation form, or a refusal document of the form {\"error\": ...} with no graph; only the object shape is checked here.",
      "anyOf": [
        {
          "type": "object",
          "required": [
            "schemaVersion",
            "manifest",
            "results",
            "proofGraph"
          ],
          "properties": {
            "schemaVersion": {
              "type": "string"
            },
            "manifest": {
              "type": "object"
            },
            "results": {
              "type": "array"
            },
            "positions": {
              "type": "array"
            },
            "conflicts": {
              "type": "array"
            },
            "issues": {
              "type": "array"
            },
            "proofGraph": {
              "type": "object"
            },
            "resultHash": {
              "type": "string"
            }
          }
        },
        {
          "type": "object",
          "required": [
            "error"
          ],
          "properties": {
            "error": {
              "type": "object"
            }
          }
        }
      ]
    },
    "Context": {
      "description": "The pinned run context: lockfile, resources, semantics release, and route. Any field may be absent — the inspector then answers with a source_unavailable limit state naming the field.",
      "type": "object",
      "properties": {
        "route": {
          "enum": [
            "cli",
            "mcp",
            "wasm",
            "sdk",
            "case"
          ]
        },
        "release": {
          "type": "string"
        },
        "programHash": {
          "type": "string"
        },
        "resolutionHash": {
          "type": "string"
        },
        "lock": {},
        "resources": {
          "type": "array"
        },
        "packages": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "additionalProperties": true
    },
    "Side": {
      "type": "object",
      "required": [
        "document"
      ],
      "properties": {
        "document": {
          "$ref": "#/$defs/EvaluationDocument"
        },
        "snapshot": {
          "type": [
            "object",
            "null"
          ],
          "description": "A snapshot of the compiled program. Without it, labels and resolved names are read from the document URNs and marked source_unavailable."
        },
        "context": {
          "anyOf": [
            {
              "$ref": "#/$defs/Context"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "Select": {
      "description": "The address of a slice: at least one field, or watch alone (watching the whole answer). Empty means a slice over every result of the document.",
      "type": "object",
      "properties": {
        "query": {
          "type": "string",
          "description": "A query id or a result id."
        },
        "rule": {
          "type": "string",
          "description": "The stable id of a rule."
        },
        "position": {
          "type": "string",
          "description": "A position id."
        },
        "node": {
          "type": "string",
          "description": "A proof-node id."
        },
        "watch": {
          "type": "array",
          "description": "Watch conditions — filters over the slice, never new nodes: applied (a rule fired), defeated (defeated), judgment (a judgment was requested), interpretation (a reading was chosen), stage (round nodes), status (position status history).", "$comment": "SPEC §47.3; SPEC §152",
          "items": {
            "type": "object",
            "required": [
              "kind"
            ],
            "properties": {
              "kind": {
                "enum": [
                  "applied",
                  "defeated",
                  "judgment",
                  "interpretation",
                  "stage",
                  "status"
                ]
              },
              "rule": {
                "type": "string"
              },
              "position": {
                "type": "string"
              },
              "status": {
                "type": "string"
              },
              "stage": {}
            },
            "additionalProperties": false
          }
        }
      },
      "additionalProperties": false
    },
    "Page": {
      "type": "object",
      "properties": {
        "cursor": {
          "type": [
            "string",
            "null"
          ]
        },
        "budgetBytes": {
          "type": "integer",
          "minimum": 1024,
          "default": 24000
        }
      },
      "additionalProperties": false
    },
    "Request": {
      "type": "object",
      "required": [
        "schema",
        "operation",
        "document"
      ],
      "properties": {
        "schema": {
          "$ref": "#/$defs/Schema"
        },
        "operation": {
          "$ref": "#/$defs/Operation"
        },
        "document": {
          "$ref": "#/$defs/EvaluationDocument"
        },
        "snapshot": {
          "type": [
            "object",
            "null"
          ]
        },
        "context": {
          "anyOf": [
            {
              "$ref": "#/$defs/Context"
            },
            {
              "type": "null"
            }
          ]
        },
        "against": {
          "anyOf": [
            {
              "$ref": "#/$defs/Side"
            },
            {
              "type": "null"
            }
          ],
          "description": "The second side of a diff; ignored by every other operation."
        },
        "select": {
          "anyOf": [
            {
              "$ref": "#/$defs/Select"
            },
            {
              "type": "null"
            }
          ]
        },
        "page": {
          "anyOf": [
            {
              "$ref": "#/$defs/Page"
            },
            {
              "type": "null"
            }
          ]
        },
        "bundle": {
          "anyOf": [
            {
              "$ref": "#/$defs/Bundle"
            },
            {
              "type": "null"
            }
          ]
        },
        "index": {
          "type": [
            "object",
            "null"
          ],
          "description": "The program editor index; read only when the verification index state is bound."
        },
        "sources": {
          "type": [
            "object",
            "null"
          ],
          "description": "Current digests of author files, uri to sha256, as presented by the adapter; the inspector never reads files itself.",
          "additionalProperties": {
            "type": "string"
          }
        }
      },
      "additionalProperties": false,
      "if": {
        "properties": {
          "operation": {
            "const": "diff"
          }
        }
      },
      "then": {
        "required": [
          "against"
        ]
      }
    },
    "Limit": {
      "type": "object",
      "required": [
        "state",
        "address",
        "note"
      ],
      "properties": {
        "state": {
          "$ref": "#/$defs/LimitState"
        },
        "address": {
          "type": "string",
          "description": "The address of what is missing or truncated: a document path, a snapshot path, a context field, or an operation name."
        },
        "note": {
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "Answer": {
      "type": "object",
      "required": [
        "schema",
        "ok",
        "operation",
        "verification",
        "limits",
        "page"
      ],
      "properties": {
        "schema": {
          "$ref": "#/$defs/Schema"
        },
        "ok": {
          "const": true
        },
        "operation": {
          "$ref": "#/$defs/Operation"
        },
        "verification": {
          "type": "object",
          "required": [
            "resultHash",
            "snapshot",
            "index"
          ],
          "properties": {
            "resultHash": {
              "$ref": "#/$defs/VerificationState"
            },
            "snapshot": {
              "$ref": "#/$defs/VerificationState"
            },
            "index": {
              "description": "bound: the parts agree with the bundle, and the bundle states one program input for program and index (single-input); consistent: the parts agree by digest, but the index was built by re-reading, or the mode is unnamed, so shared origin is not established; mismatch: the bundle names different artifacts; unavailable: no index or bundle. No state proves who produced the bundle — only that the presented parts agree.",
              "enum": [
                "bound",
                "consistent",
                "mismatch",
                "unavailable"
              ]
            }
          },
          "additionalProperties": false
        },
        "limits": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/Limit"
          }
        },
        "page": {
          "type": "object",
          "required": [
            "next"
          ],
          "properties": {
            "next": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          "additionalProperties": false
        },
        "summary": {
          "type": "object",
          "description": "The summary body: origin card, queries, positions, issues, conflicts, and judgment requests."
        },
        "slice": {
          "type": "object",
          "description": "The slice body."
        },
        "diff": {
          "type": "object",
          "description": "The diff body: context, result, and justification."
        },
        "locate": {
          "type": "object",
          "description": "The locate body: the declaration address and its source spans."
        },
        "runId": {
          "type": "string",
          "description": "The id of a saved run — consumed by the law.inspect language-server route."
        }
      },
      "additionalProperties": false
    },
    "RequestError": {
      "description": "The single error path: the request cannot be read. Everything else is a limit state inside a well-formed answer.",
      "type": "object",
      "required": [
        "schema",
        "ok",
        "error"
      ],
      "properties": {
        "schema": {
          "$ref": "#/$defs/Schema"
        },
        "ok": {
          "const": false
        },
        "error": {
          "type": "object",
          "required": [
            "code",
            "message"
          ],
          "properties": {
            "code": {
              "enum": [
                "REQUEST_NOT_OBJECT",
                "SCHEMA_MISSING",
                "SCHEMA_MISMATCH",
                "OPERATION_MISSING",
                "OPERATION_UNKNOWN",
                "DOCUMENT_MISSING",
                "AGAINST_MISSING",
                "AGAINST_NOT_OBJECT",
                "AGAINST_DOCUMENT_MISSING",
                "SELECT_NOT_OBJECT",
                "PAGE_NOT_OBJECT"
              ]
            },
            "message": {
              "type": "string"
            }
          },
          "additionalProperties": false
        }
      },
      "additionalProperties": false
    },
    "Bundle": {
      "description": "A bundle of the document, the exact snapshot, and the editor index, written by the compiler adapter that ran the evaluation, with machine output saved. Hashes keep the parts checkable; the link between them is vouched for by the producer, never by a field’s own claim.",
      "type": "object",
      "required": [
        "schema",
        "producer",
        "document",
        "snapshot",
        "index"
      ],
      "properties": {
        "schema": {
          "const": "law.inspection-bundle/0.1"
        },
        "producer": {
          "type": "object",
          "required": [
            "name",
            "version"
          ],
          "properties": {
            "name": {
              "type": "string"
            },
            "version": {
              "type": "string"
            }
          },
          "additionalProperties": false
        },
        "document": {
          "type": "object",
          "required": [
            "resultHash"
          ],
          "properties": {
            "file": {
              "type": "string"
            },
            "resultHash": {
              "type": [
                "string",
                "null"
              ]
            },
            "digest": {
              "type": "string",
              "description": "Digest of the document’s canonical bytes; also pins a refusal document, which has no result hash."
            }
          },
          "additionalProperties": false
        },
        "snapshot": {
          "type": "object",
          "required": [
            "theoryHash"
          ],
          "properties": {
            "file": {
              "type": "string"
            },
            "pointer": {
              "type": "string"
            },
            "theoryHash": {
              "type": [
                "string",
                "null"
              ]
            },
            "artifactHash": {
              "type": [
                "string",
                "null"
              ]
            },
            "pinnedBy": {
              "type": "string"
            }
          },
          "additionalProperties": false
        },
        "index": {
          "anyOf": [
            {
              "type": "null"
            },
            {
              "type": "object",
              "required": [
                "digest"
              ],
              "properties": {
                "file": {
                  "type": "string"
                },
                "digest": {
                  "type": "string"
                },
                "partial": {},
                "inputMode": {
                  "description": "single-input: model and index came from one parsed input; reread: the root-package index was rebuilt by re-reading after the run against a lockfile-checked dependency context.",
                  "enum": [
                    "single-input",
                    "reread"
                  ]
                }
              },
              "additionalProperties": false
            }
          ]
        },
        "indexUnavailable": {
          "type": "string"
        },
        "sources": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "uri",
              "sha256"
            ],
            "properties": {
              "uri": {
                "type": "string"
              },
              "sha256": {
                "type": "string"
              }
            },
            "additionalProperties": false
          }
        },
        "question": {
          "type": "object"
        },
        "inputs": {
          "type": "object"
        }
      },
      "additionalProperties": false
    }
  }
}
