{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://yarrasys.dev/schema/yarramate-design-step.schema.json",
  "title": "YarraMate design step",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "format",
    "workspace",
    "catalogue",
    "progress",
    "step"
  ],
  "properties": {
    "format": {
      "const": "yarramate/design-step/v1"
    },
    "workspace": {
      "type": "string",
      "minLength": 1
    },
    "catalogue": {
      "type": "string",
      "minLength": 1
    },
    "progress": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "questions",
        "openQuestions",
        "open",
        "waves"
      ],
      "properties": {
        "questions": {
          "type": "integer",
          "minimum": 0
        },
        "openQuestions": {
          "type": "integer",
          "minimum": 0
        },
        "open": {
          "type": "integer",
          "minimum": 0
        },
        "waves": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "open"
            ],
            "properties": {
              "id": {
                "type": "string",
                "minLength": 1
              },
              "open": {
                "type": "integer",
                "minimum": 0
              }
            }
          }
        }
      }
    },
    "step": {
      "oneOf": [
        {
          "type": "null"
        },
        {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "questionId",
            "wave",
            "scope",
            "authority",
            "question",
            "materiality",
            "resolution",
            "trigger"
          ],
          "properties": {
            "questionId": {
              "type": "string",
              "minLength": 1
            },
            "wave": {
              "type": "string",
              "minLength": 1
            },
            "scope": {
              "enum": [
                "workspace",
                "subject"
              ]
            },
            "authority": {
              "enum": [
                "human",
                "agent",
                "either"
              ]
            },
            "question": {
              "type": "string",
              "minLength": 1
            },
            "askPlain": {
              "type": "string",
              "minLength": 1
            },
            "materiality": {
              "type": "string",
              "minLength": 1
            },
            "resolution": {
              "type": "string",
              "minLength": 1
            },
            "trigger": {
              "description": "The catalogue trigger, verbatim: the conditions that opened this question, i.e. its machine-readable answer shape.",
              "type": "array",
              "minItems": 1,
              "items": {
                "$ref": "#/$defs/condition"
              }
            },
            "subject": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "id"
              ],
              "properties": {
                "id": {
                  "type": "string",
                  "minLength": 1
                },
                "name": {
                  "type": "string",
                  "minLength": 1
                }
              }
            },
            "remainingSubjects": {
              "type": "integer",
              "minimum": 1
            },
            "openSubjects": {
              "type": "array",
              "minItems": 1,
              "items": {
                "type": "string",
                "minLength": 1
              }
            },
            "since": {
              "type": "string"
            }
          }
        }
      ]
    },
    "slice": {
      "type": "string",
      "minLength": 1
    }
  },
  "$defs": {
    "condition": {
      "description": "One deterministic trigger condition. All conditions in a trigger must hold (AND) for the question to be open.",
      "oneOf": [
        {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "condition",
            "predicate"
          ],
          "properties": {
            "condition": {
              "const": "missing-claim"
            },
            "predicate": {
              "$ref": "#/$defs/claimPredicate"
            }
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "condition",
            "kinds",
            "direction"
          ],
          "properties": {
            "condition": {
              "const": "missing-relationship"
            },
            "kinds": {
              "type": "array",
              "minItems": 1,
              "uniqueItems": true,
              "items": {
                "$ref": "#/$defs/qualifiedKind"
              }
            },
            "direction": {
              "enum": [
                "incoming",
                "outgoing",
                "any"
              ]
            },
            "kindMatching": {
              "enum": [
                "exact",
                "descendants"
              ]
            }
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "condition"
          ],
          "properties": {
            "condition": {
              "const": "isolated"
            }
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "condition",
            "kinds"
          ],
          "properties": {
            "condition": {
              "const": "no-subject-of-kind"
            },
            "kinds": {
              "type": "array",
              "minItems": 1,
              "uniqueItems": true,
              "items": {
                "$ref": "#/$defs/qualifiedKind"
              }
            },
            "kindMatching": {
              "enum": [
                "exact",
                "descendants"
              ],
              "default": "descendants"
            }
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "condition",
            "kinds"
          ],
          "properties": {
            "condition": {
              "const": "has-subject-of-kind"
            },
            "kinds": {
              "type": "array",
              "minItems": 1,
              "uniqueItems": true,
              "items": {
                "$ref": "#/$defs/qualifiedKind"
              }
            },
            "kindMatching": {
              "enum": [
                "exact",
                "descendants"
              ],
              "default": "descendants"
            }
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "condition",
            "kinds",
            "atLeast"
          ],
          "properties": {
            "condition": {
              "const": "below-subject-count"
            },
            "kinds": {
              "type": "array",
              "minItems": 1,
              "uniqueItems": true,
              "items": {
                "$ref": "#/$defs/qualifiedKind"
              }
            },
            "atLeast": {
              "description": "The floor the kind's population must reach. At least 2: atLeast 1 is no-subject-of-kind under another name, and the engine refuses it (YM918).",
              "type": "integer",
              "minimum": 1
            },
            "kindMatching": {
              "enum": [
                "exact",
                "descendants"
              ],
              "default": "descendants"
            }
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "condition"
          ],
          "properties": {
            "condition": {
              "const": "no-state-defined"
            }
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "condition",
            "kinds",
            "direction",
            "counterpartKinds"
          ],
          "properties": {
            "condition": {
              "const": "missing-linkage"
            },
            "kinds": {
              "type": "array",
              "minItems": 1,
              "uniqueItems": true,
              "items": {
                "$ref": "#/$defs/qualifiedKind"
              }
            },
            "direction": {
              "enum": [
                "outgoing",
                "incoming"
              ]
            },
            "counterpartKinds": {
              "type": "array",
              "minItems": 1,
              "uniqueItems": true,
              "items": {
                "$ref": "#/$defs/qualifiedKind"
              }
            },
            "kindMatching": {
              "enum": [
                "exact",
                "descendants"
              ],
              "default": "descendants"
            }
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "condition",
            "kinds",
            "direction",
            "counterpartKinds"
          ],
          "properties": {
            "condition": {
              "const": "has-linkage"
            },
            "kinds": {
              "type": "array",
              "minItems": 1,
              "uniqueItems": true,
              "items": {
                "$ref": "#/$defs/qualifiedKind"
              }
            },
            "direction": {
              "enum": [
                "outgoing",
                "incoming",
                "either"
              ]
            },
            "counterpartKinds": {
              "type": "array",
              "minItems": 1,
              "uniqueItems": true,
              "items": {
                "$ref": "#/$defs/qualifiedKind"
              }
            },
            "kindMatching": {
              "enum": [
                "exact",
                "descendants"
              ],
              "default": "descendants"
            }
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "condition",
            "kinds",
            "direction",
            "counterpartKinds"
          ],
          "properties": {
            "condition": {
              "const": "exists-linkage"
            },
            "kinds": {
              "type": "array",
              "minItems": 1,
              "uniqueItems": true,
              "items": {
                "$ref": "#/$defs/qualifiedKind"
              }
            },
            "direction": {
              "enum": [
                "outgoing",
                "incoming",
                "either"
              ]
            },
            "counterpartKinds": {
              "type": "array",
              "minItems": 1,
              "uniqueItems": true,
              "items": {
                "$ref": "#/$defs/qualifiedKind"
              }
            },
            "kindMatching": {
              "enum": [
                "exact",
                "descendants"
              ],
              "default": "descendants"
            }
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "condition",
            "kinds",
            "direction",
            "counterpartKinds"
          ],
          "properties": {
            "condition": {
              "const": "no-linkage-exists"
            },
            "kinds": {
              "type": "array",
              "minItems": 1,
              "uniqueItems": true,
              "items": {
                "$ref": "#/$defs/qualifiedKind"
              }
            },
            "direction": {
              "enum": [
                "outgoing",
                "incoming",
                "either"
              ]
            },
            "counterpartKinds": {
              "type": "array",
              "minItems": 1,
              "uniqueItems": true,
              "items": {
                "$ref": "#/$defs/qualifiedKind"
              }
            },
            "kindMatching": {
              "enum": [
                "exact",
                "descendants"
              ],
              "default": "descendants"
            }
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "condition",
            "kinds"
          ],
          "properties": {
            "condition": {
              "const": "missing-constraint"
            },
            "kinds": {
              "type": "array",
              "minItems": 1,
              "uniqueItems": true,
              "items": {
                "$ref": "#/$defs/qualifiedKind"
              }
            },
            "kindMatching": {
              "enum": [
                "exact",
                "descendants"
              ],
              "default": "descendants"
            }
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "description": "The subject is an endpoint of at least one flow relationship that has no yarramate/flow/content claim.",
          "required": [
            "condition"
          ],
          "properties": {
            "condition": {
              "const": "missing-flow-content"
            }
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "condition",
            "predicate",
            "direction"
          ],
          "properties": {
            "condition": {
              "const": "missing-reference"
            },
            "predicate": {
              "$ref": "#/$defs/claimPredicate"
            },
            "direction": {
              "enum": [
                "outgoing",
                "incoming"
              ]
            }
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "condition",
            "topic"
          ],
          "properties": {
            "condition": {
              "const": "missing-attestation"
            },
            "topic": {
              "type": "string",
              "pattern": "^[a-z][a-z0-9-]*$"
            }
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "description": "The subject resembles another subject of the same kind closely enough to be the same thing under two names, and no yarramate/identity/distinct-from claim dismisses the pair. Deterministic and lexical; the algorithm and thresholds are stated in ADR 0077. Questions using it may interpolate {counterparts}.",
          "required": [
            "condition"
          ],
          "properties": {
            "condition": {
              "const": "near-duplicate"
            }
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "description": "The subject's kind is never tested by anything the compiler can check: it participates in no relationship whose kind pins the aspect at the subject's end, so reclassifying it to any other kind of any other aspect would still compile. The kind is a label rather than a constraint (ADR 0083).",
          "required": [
            "condition"
          ],
          "properties": {
            "condition": {
              "const": "unconstrained-kind"
            }
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "description": "The subject supersedes a predecessor that is still current, and does not say in what respect. A succession that replaced its predecessor outright says so by the predecessor being gone; one where both remain is usually partial, and the respect is the part a reader needs (ADR 0109).",
          "required": [
            "condition"
          ],
          "properties": {
            "condition": {
              "const": "unscoped-succession"
            }
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "description": "The workspace holds at least one concept (#334, ADR 0125). The guard a late wave needs to say \"only once the model has substance\": an empty model is not an architecture at rest, it has not started, and asking it how the planned architecture becomes real greets someone ahead of question one.",
          "required": [
            "condition"
          ],
          "properties": {
            "condition": {
              "const": "has-any-subject"
            }
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "description": "The workspace's evidence overlay records observations and every one is a frictionless confirmation: no contradicted, unknown, or not-observed result, and no recorded search (ADR 0107). A discovery that never records anything but success never tested a claim it might fail. The one condition that reads the evidence overlay rather than the compiled graph; where the evaluating consumer supplies no overlay it stays quiet (ADR 0120).",
          "required": [
            "condition"
          ],
          "properties": {
            "condition": {
              "const": "unchallenged-evidence"
            }
          }
        }
      ]
    },
    "claimPredicate": {
      "type": "string",
      "pattern": "^[a-z][a-z0-9/@.#-]*$"
    },
    "qualifiedKind": {
      "type": "string",
      "pattern": "^[a-z][a-z0-9/-]*@[0-9][0-9A-Za-z.-]*#[A-Za-z][A-Za-z0-9-]*$"
    }
  }
}
