{
  "$comment": "generated by canon-docs, do not edit",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://beyond10x.github.io/canon/schemas/protocol-1.schema.json",
  "title": "protocol/1",
  "description": "A `protocol/1` source document as written.",
  "$ref": "#/$defs/Protocol",
  "$defs": {
    "Identifier": {
      "description": "A well-formed identifier is not empty, and without whitespace, control characters or Unicode format characters (general category Cf). The pattern checks only for whitespace; Canon also refuses control and Unicode format characters.",
      "type": "string",
      "minLength": 1,
      "pattern": "^\\S+$"
    },
    "Age": {
      "description": "A length of time: a whole number without leading zeros, followed by `s`, `m`, `h` or `d` (`5m`, `24h`). Canon also refuses an age too long to count in seconds.",
      "type": "string",
      "pattern": "^(0|[1-9][0-9]*)[smhd]$"
    },
    "ScalarIdentifier": {
      "description": "An identifier, or a boolean or a number written unquoted, which Canon reads as its text (`true`, `2`).",
      "anyOf": [
        {
          "$ref": "#/$defs/Identifier"
        },
        {
          "type": "boolean"
        },
        {
          "type": "number"
        }
      ]
    },
    "Protocol": {
      "description": "A `protocol/1` source document as written.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "format": {
          "description": "The document format; the validator accepts only `protocol/1`.",
          "type": "string",
          "const": "protocol/1"
        },
        "protocol": {
          "$ref": "#/$defs/ProtocolHeader"
        },
        "artifacts": {
          "type": "object",
          "propertyNames": {
            "$ref": "#/$defs/Identifier"
          },
          "additionalProperties": {
            "$ref": "#/$defs/Artifact"
          }
        },
        "evidence_kinds": {
          "type": "object",
          "propertyNames": {
            "$ref": "#/$defs/Identifier"
          },
          "additionalProperties": {
            "$ref": "#/$defs/EvidenceKind"
          }
        },
        "claims": {
          "type": "object",
          "propertyNames": {
            "$ref": "#/$defs/Identifier"
          },
          "additionalProperties": {
            "$ref": "#/$defs/Claim"
          }
        },
        "obligations": {
          "type": "object",
          "propertyNames": {
            "$ref": "#/$defs/Identifier"
          },
          "additionalProperties": {
            "$ref": "#/$defs/Obligation"
          }
        },
        "actions": {
          "type": "object",
          "propertyNames": {
            "$ref": "#/$defs/Identifier"
          },
          "additionalProperties": {
            "$ref": "#/$defs/Action"
          }
        },
        "outcomes": {
          "type": "object",
          "propertyNames": {
            "$ref": "#/$defs/Identifier"
          },
          "additionalProperties": {
            "$ref": "#/$defs/Outcome"
          }
        },
        "invalidation": {
          "description": "The invalidation rules, keyed by rule id; a protocol without the section declares none.",
          "type": "object",
          "propertyNames": {
            "$ref": "#/$defs/Identifier"
          },
          "additionalProperties": {
            "$ref": "#/$defs/InvalidationRule"
          }
        },
        "case": {
          "description": "What a case governed by the protocol gives when it opens: its case inputs. A protocol without the section declares no input.",
          "$ref": "#/$defs/CaseSection"
        },
        "independence_dimensions": {
          "description": "The independence dimensions the protocol's evidence matches may demand, keyed by dimension id; a protocol without the section declares none.",
          "type": "object",
          "propertyNames": {
            "$ref": "#/$defs/Identifier"
          },
          "additionalProperties": {
            "$ref": "#/$defs/IndependenceDimension"
          }
        }
      },
      "required": [
        "format",
        "protocol"
      ]
    },
    "ProtocolHeader": {
      "description": "The protocol's identity: id and revision.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "id": {
          "$ref": "#/$defs/Identifier"
        },
        "revision": {
          "type": "integer",
          "minimum": 0
        },
        "description": {
          "type": "string"
        }
      },
      "required": [
        "id",
        "revision"
      ]
    },
    "Artifact": {
      "description": "A thing whose revisions evidence is bound to.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "description": {
          "type": "string"
        }
      }
    },
    "EvidenceKind": {
      "description": "A kind of evidence the protocol admits.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "description": {
          "type": "string"
        },
        "max_age": {
          "description": "How old a record of this kind may be and still apply: at an evaluation instant later than its `observed_at` by more than this, it is excluded as expired (design § 8).",
          "$ref": "#/$defs/Age"
        }
      }
    },
    "Claim": {
      "description": "A proposition whose value is established from evidence by its predicate.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "description": {
          "type": "string"
        },
        "true_when": {
          "$ref": "#/$defs/Predicate"
        }
      },
      "required": [
        "true_when"
      ]
    },
    "Obligation": {
      "description": "Something that must be done before the case can be complete. It is discharged only when its discharge predicate, over claim values, evaluates true (design § 8). One with an applicability predicate applies only when that predicate is not false: false, it is not applicable.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "description": {
          "type": "string"
        },
        "discharged_when": {
          "$ref": "#/$defs/Predicate"
        },
        "applicable_when": {
          "description": "When the obligation applies, over claim values and case inputs; always, when absent.",
          "$ref": "#/$defs/Predicate"
        }
      },
      "required": [
        "discharged_when"
      ]
    },
    "Action": {
      "description": "A semantically named possibility: what it needs, what authority it requires, what effect it has and what evidence it may produce (design § 10).",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "description": {
          "type": "string"
        },
        "precondition": {
          "$ref": "#/$defs/Predicate"
        },
        "requires": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/CapabilityRequirement"
          }
        },
        "effect": {
          "$ref": "#/$defs/Identifier"
        },
        "may_produce": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/EvidenceProduction"
          }
        },
        "arguments": {
          "description": "The JSON Schema, in Canon's argument-schema dialect, that the action's arguments satisfy. Absent: the action takes no arguments; a runner accepts only `{}`. Canon never validates arguments at run time: the runner that calls the action validates them against the schema, and `canon validate` holds the schema to the dialect (`action-arguments`)."
        },
        "case_open": {
          "description": "The child case the action opens (story:case-composition): a case governed by another protocol, about a declared artifact. Absent: the action opens no case. Canon opens nothing itself; whoever takes the action opens the child case. A case has one commission, and a second party works through a child case: this is the one primitive by which a case hands work to another party (D207).",
          "$ref": "#/$defs/CaseOpening"
        }
      }
    },
    "Outcome": {
      "description": "A legitimate terminal interpretation of a case and what it requires: a predicate, or an explicit decision (`requires: decision: <name>`).",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "description": {
          "type": "string"
        },
        "requires": {
          "$ref": "#/$defs/OutcomeRequirement"
        }
      },
      "required": [
        "requires"
      ]
    },
    "InvalidationRule": {
      "description": "An invalidation rule: a change of its upstream artifact's revision invalidates, for the claims it names and every claim built on them, the evidence observed against an earlier revision of that artifact (design § 4.1, CANON-INVALIDATION-001).",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "description": {
          "type": "string"
        },
        "upstream": {
          "description": "The artifact whose revision the rule watches.",
          "$ref": "#/$defs/Identifier"
        },
        "invalidates": {
          "description": "The claims whose support a change of that revision invalidates.",
          "type": "array",
          "items": {
            "$ref": "#/$defs/Identifier"
          }
        }
      },
      "required": [
        "upstream",
        "invalidates"
      ]
    },
    "CaseSection": {
      "description": "The protocol's `case:` section.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "inputs": {
          "description": "The case inputs, keyed by input id.",
          "type": "object",
          "propertyNames": {
            "$ref": "#/$defs/Identifier"
          },
          "additionalProperties": {
            "$ref": "#/$defs/CaseInput"
          }
        }
      }
    },
    "IndependenceDimension": {
      "description": "One independence dimension: a relation between who produced a record and the case's work, which the trusted context resolves for each producer and Canon reads from the case.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "description": {
          "type": "string"
        }
      }
    },
    "Predicate": {
      "description": "A predicate over evidence and claim values.",
      "oneOf": [
        {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "all": {
              "description": "True when every member is true; true when empty.",
              "type": "array",
              "items": {
                "$ref": "#/$defs/Predicate"
              }
            }
          },
          "required": [
            "all"
          ]
        },
        {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "any": {
              "description": "True when some member is true; false when empty.",
              "type": "array",
              "items": {
                "$ref": "#/$defs/Predicate"
              }
            }
          },
          "required": [
            "any"
          ]
        },
        {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "not": {
              "$ref": "#/$defs/Predicate"
            }
          },
          "required": [
            "not"
          ]
        },
        {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "evidence": {
              "$ref": "#/$defs/EvidenceMatch"
            }
          },
          "required": [
            "evidence"
          ]
        },
        {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "claim": {
              "$ref": "#/$defs/Identifier"
            },
            "is": {
              "$ref": "#/$defs/Truth"
            }
          },
          "required": [
            "claim"
          ]
        },
        {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "input": {
              "description": "True when the case's value of the input is one of the values listed, false otherwise.",
              "$ref": "#/$defs/Identifier"
            },
            "in": {
              "description": "The values the test is true for, written `in`.",
              "type": "array",
              "items": {
                "$ref": "#/$defs/ScalarIdentifier"
              }
            }
          },
          "required": [
            "input"
          ]
        },
        {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "first": {
              "description": "Whether the first record of a kind, in the evidence history, has a result.",
              "$ref": "#/$defs/FirstResult"
            }
          },
          "required": [
            "first"
          ]
        },
        {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "before": {
              "description": "Whether the first record of one kind, in the evidence history, was observed strictly before the first record of another.",
              "$ref": "#/$defs/EvidenceOrder"
            }
          },
          "required": [
            "before"
          ]
        },
        {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "after": {
              "description": "Whether a record of a kind with a result, in the evidence history, was observed strictly after the first record of a kind.",
              "$ref": "#/$defs/EvidenceAfter"
            }
          },
          "required": [
            "after"
          ]
        },
        {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "since": {
              "description": "Whether a record of a kind with a result, at the subject revision of the latest record of a kind in the evidence history, was observed after that record.",
              "$ref": "#/$defs/EvidenceSince"
            }
          },
          "required": [
            "since"
          ]
        },
        {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "children": {
              "description": "Whether every child case of the case ended with one of the outcomes listed, over its `case_outcome` records (story:case-composition).",
              "$ref": "#/$defs/ChildOutcomes"
            }
          },
          "required": [
            "children"
          ]
        }
      ]
    },
    "CapabilityRequirement": {
      "description": "One capability an action requires authority for.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "capability": {
          "$ref": "#/$defs/Identifier"
        }
      },
      "required": [
        "capability"
      ]
    },
    "EvidenceProduction": {
      "description": "One evidence kind an action may produce.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "evidence": {
          "$ref": "#/$defs/Identifier"
        }
      },
      "required": [
        "evidence"
      ]
    },
    "CaseOpening": {
      "description": "What an action's `case_open` names: the protocol the child case is governed by and the artifact it is about, never an existing case. No run-time check keeps a case from opening one under its own protocol (D206): `canon validate` refuses an opening under the protocol's own id, and the library function `b10x_canon::ir::check_openings` refuses a set of protocols whose openings form a cycle, naming it in the order its openings go, from its least protocol id.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "protocol": {
          "description": "The protocol the child case is governed by.",
          "$ref": "#/$defs/Identifier"
        },
        "subject": {
          "description": "The declared artifact the child case is about.",
          "$ref": "#/$defs/Identifier"
        }
      },
      "required": [
        "protocol",
        "subject"
      ]
    },
    "OutcomeRequirement": {
      "description": "What an outcome requires.",
      "oneOf": [
        {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "decision": {
              "description": "The outcome is legitimate only with an explicit decision of this name, for the outcome, taken at the case snapshot's current revision.",
              "$ref": "#/$defs/Identifier"
            }
          },
          "required": [
            "decision"
          ]
        },
        {
          "description": "The outcome is legitimate when the predicate is `true`.",
          "$ref": "#/$defs/Predicate"
        }
      ]
    },
    "CaseInput": {
      "description": "A case input: configuration a case fixes when it opens, one of a closed, non-empty list of values. Not evidence, so no evaluation has an unknown input.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "description": {
          "type": "string"
        },
        "values": {
          "description": "The values the input may take.",
          "type": "array",
          "items": {
            "$ref": "#/$defs/ScalarIdentifier"
          }
        }
      },
      "required": [
        "values"
      ]
    },
    "EvidenceMatch": {
      "description": "Matches evidence of one kind, optionally with one result, optionally only evidence about one declared artifact (a match that names a subject reads only the records whose subject it is), and optionally only evidence whose producer the case lists as independent on every dimension `independent_on` names.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "kind": {
          "$ref": "#/$defs/Identifier"
        },
        "result": {
          "type": "string"
        },
        "subject": {
          "$ref": "#/$defs/Identifier"
        },
        "independent_on": {
          "description": "The independence the match demands of a record's producer: declared dimensions, not empty, each once. A match without it reads records whoever produced them.",
          "type": "array",
          "items": {
            "$ref": "#/$defs/Identifier"
          }
        }
      },
      "required": [
        "kind"
      ]
    },
    "FirstResult": {
      "description": "An order form: whether the first record of `kind`, about `subject` when it names one, has `result`: the records at the earliest instant at the evaluation's resolution. It reads every record of the kind the evidence check accepted, excluded or not.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "kind": {
          "description": "The evidence kind whose first record is read.",
          "$ref": "#/$defs/Identifier"
        },
        "result": {
          "description": "The result that first record is to have.",
          "type": "string"
        },
        "subject": {
          "description": "The declared artifact the records read are about; without it, records about any artifact.",
          "$ref": "#/$defs/Identifier"
        }
      },
      "required": [
        "kind",
        "result"
      ]
    },
    "EvidenceOrder": {
      "description": "An order form: whether the first record of kind `first` was observed strictly before the first record of kind `then`, both about `subject` when it names one: the earliest instants of the two kinds at the evaluation's resolution, an equal pair not ordered. It reads every record of the two kinds the evidence check accepted, excluded or not.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "first": {
          "description": "The evidence kind whose first record is to come first.",
          "$ref": "#/$defs/Identifier"
        },
        "then": {
          "description": "The evidence kind whose first record is to come after it; another kind than `first`.",
          "$ref": "#/$defs/Identifier"
        },
        "subject": {
          "description": "The declared artifact the records of both kinds are about; without it, records about any artifact.",
          "$ref": "#/$defs/Identifier"
        }
      },
      "required": [
        "first",
        "then"
      ]
    },
    "EvidenceAfter": {
      "description": "An order form: whether some record of `then.kind` with result `then.result` was observed strictly after the first record of kind `first`, all about `subject` when it names one: after the earliest instant of `first` at the evaluation's resolution. It reads every record of the two kinds the evidence check accepted, excluded or not. `first` and `then.kind` may be one kind: a record is not later than itself.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "first": {
          "description": "The evidence kind whose first record the later one is to come after.",
          "$ref": "#/$defs/Identifier"
        },
        "then": {
          "description": "The record that is to come after it: its kind and its result.",
          "$ref": "#/$defs/LaterRecord"
        },
        "subject": {
          "description": "The declared artifact the records of both kinds are about; without it, records about any artifact.",
          "$ref": "#/$defs/Identifier"
        }
      },
      "required": [
        "first",
        "then"
      ]
    },
    "EvidenceSince": {
      "description": "An order form: whether a record of `then.kind` with result `then.result`, about the subject and subject revision of the latest record of kind `last`, was observed after that record, all about `subject` when it names one. It reads every record of the two kinds the evidence check accepted, excluded or not. `last` and `then.kind` may be one kind: a record is not later than itself.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "last": {
          "description": "The evidence kind whose latest record the later one is to come after, at its revision.",
          "$ref": "#/$defs/Identifier"
        },
        "then": {
          "description": "The record that is to come after it: its kind and its result.",
          "$ref": "#/$defs/LaterRecord"
        },
        "subject": {
          "description": "The declared artifact the records of both kinds are about; without it, records about any artifact.",
          "$ref": "#/$defs/Identifier"
        }
      },
      "required": [
        "last",
        "then"
      ]
    },
    "ChildOutcomes": {
      "description": "The form over the case's child cases, written `{children: {in: [<outcome>, ...]}}`: whether every child case ended with one of the outcomes listed. It reads every `case_outcome` record the evidence check accepted, as the order forms read the history: `unknown` with no record, `false` when a record's outcome is neither listed nor `open` (a child that ended outside the set), otherwise `unknown` when a child is still `open` and `true` when every child ended with a listed outcome.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "in": {
          "description": "The outcomes a child case may have ended with, written `in`: not empty, each once, never `open`.",
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "required": [
        "in"
      ]
    },
    "Truth": {
      "description": "A three-valued truth value. `Unknown` is not `False`.",
      "oneOf": [
        {
          "type": "boolean"
        },
        {
          "enum": [
            "true",
            "false",
            "unknown"
          ]
        }
      ]
    },
    "LaterRecord": {
      "description": "What an `after` form reads later than the first record of its `first` kind, and a `since` form later than the latest record of its `last` kind: a record of `kind` with `result`.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "kind": {
          "description": "The evidence kind of the later record.",
          "$ref": "#/$defs/Identifier"
        },
        "result": {
          "description": "The result the later record is to have.",
          "type": "string"
        }
      },
      "required": [
        "kind",
        "result"
      ]
    }
  }
}
