{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "mindzie.process-context-graph 1.0",
  "description": "The process context graph: a structured description of how a process actually works, built from a project's event log, written so that a person can check it and an AI agent can load it. Every field is present, no value is null, and the document carries no other field. The shape is stated in words in the Process Context Graph report card's prompt (studio/cardprompts/process-context-graph.txt); a test keeps that prompt and this file the same. What each part means and where it comes from: Documentation/AIProcessIntelligence/reference/process-context-graph.md.",
  "type": "object",
  "properties": {
    "schema": {
      "description": "The name of this shape. Only a document carrying this name is held to this schema.",
      "const": "mindzie.process-context-graph"
    },
    "schema_version": {
      "description": "The version of the shape.",
      "const": "1.0"
    },
    "source": {
      "description": "The data the graph was built from: which version of the project's data, a digest of the log, what was used as the case, how many cases and events, the period, and whether times are working time or clock time. Counted.",
      "type": "object",
      "properties": {
        "data_version": {
          "type": "string"
        },
        "log_digest": {
          "type": "string"
        },
        "case_notion": {
          "type": "string"
        },
        "cases": {
          "type": "integer",
          "minimum": 0
        },
        "events": {
          "type": "integer",
          "minimum": 0
        },
        "period_start": {
          "type": "string"
        },
        "period_end": {
          "type": "string"
        },
        "time_basis": {
          "enum": [
            "working",
            "clock"
          ]
        }
      },
      "required": [
        "data_version",
        "log_digest",
        "case_notion",
        "cases",
        "events",
        "period_start",
        "period_end",
        "time_basis"
      ],
      "additionalProperties": false
    },
    "process": {
      "description": "What one case represents and what the process appears to be for. The AI's reading of the endings and the activity names.",
      "type": "object",
      "properties": {
        "case_represents": {
          "type": "string"
        },
        "objective": {
          "type": "string"
        },
        "evidence": {
          "$ref": "#/definitions/evidence"
        }
      },
      "required": [
        "case_represents",
        "objective",
        "evidence"
      ],
      "additionalProperties": false
    },
    "success_criteria": {
      "description": "How a successful case is recognised in the data, each with the share of cases that meets it. The statement is the AI's; the share is counted.",
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "statement": {
            "type": "string"
          },
          "test": {
            "type": "string"
          },
          "share_met": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "evidence": {
            "$ref": "#/definitions/evidence"
          }
        },
        "required": [
          "id",
          "statement",
          "test",
          "share_met",
          "evidence"
        ],
        "additionalProperties": false
      }
    },
    "outcomes": {
      "description": "Every way a case ends, with its cases and share. The counts are counted; which ending is success, failure, open or other is the AI's decision, stated in the report.",
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "end_activity": {
            "type": "string"
          },
          "kind": {
            "enum": [
              "success",
              "failure",
              "open",
              "other"
            ]
          },
          "cases": {
            "type": "integer",
            "minimum": 0
          },
          "share": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          }
        },
        "required": [
          "id",
          "end_activity",
          "kind",
          "cases",
          "share"
        ],
        "additionalProperties": false
      }
    },
    "stages": {
      "description": "The stages a case moves through, in order, with the activities in each. The grouping is the AI's.",
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "activities": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/plain"
            }
          }
        },
        "required": [
          "id",
          "name",
          "activities"
        ],
        "additionalProperties": false
      }
    },
    "nodes": {
      "description": "One entry per activity, plus the start and the end: how many cases and events, how many cases repeat it, the typical time to the next step, who does it and which object types it touches. Counted.",
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "kind": {
            "enum": [
              "start",
              "end",
              "activity"
            ]
          },
          "label": {
            "type": "string"
          },
          "stage": {
            "type": "string"
          },
          "cases": {
            "type": "integer",
            "minimum": 0
          },
          "events": {
            "type": "integer",
            "minimum": 0
          },
          "cases_repeating": {
            "type": "integer",
            "minimum": 0
          },
          "median_hours_to_next": {
            "type": "number",
            "minimum": 0
          },
          "roles": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/plain"
            }
          },
          "object_types": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/plain"
            }
          },
          "evidence": {
            "$ref": "#/definitions/evidence"
          }
        },
        "required": [
          "id",
          "kind",
          "label",
          "stage",
          "cases",
          "events",
          "cases_repeating",
          "median_hours_to_next",
          "roles",
          "object_types",
          "evidence"
        ],
        "additionalProperties": false
      }
    },
    "edges": {
      "description": "One entry per hand-off from one node to the next: its cases, its share of the cases leaving the first node, the typical wait and the wait of the slowest cases. Counted; the kind (normal, allowed, rework, skip, exception, escalation) is the AI's classification by the cut it states.",
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "from": {
            "type": "string"
          },
          "to": {
            "type": "string"
          },
          "kind": {
            "enum": [
              "normal",
              "allowed",
              "rework",
              "skip",
              "exception",
              "escalation"
            ]
          },
          "cases": {
            "type": "integer",
            "minimum": 0
          },
          "share_of_from": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "median_wait_hours": {
            "type": "number",
            "minimum": 0
          },
          "slow_wait_hours": {
            "type": "number",
            "minimum": 0
          },
          "evidence": {
            "$ref": "#/definitions/evidence"
          }
        },
        "required": [
          "id",
          "from",
          "to",
          "kind",
          "cases",
          "share_of_from",
          "median_wait_hours",
          "slow_wait_hours",
          "evidence"
        ],
        "additionalProperties": false
      }
    },
    "variants": {
      "description": "The paths cases follow: the main path, the allowed variations and the exception paths with at least one case in a hundred. Counted; the class is by the AI's stated cut.",
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "path": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/plain"
            }
          },
          "class": {
            "enum": [
              "main",
              "allowed",
              "exception"
            ]
          },
          "cases": {
            "type": "integer",
            "minimum": 0
          },
          "share": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          }
        },
        "required": [
          "id",
          "path",
          "class",
          "cases",
          "share"
        ],
        "additionalProperties": false
      }
    },
    "model": {
      "description": "A process tree discovered from the paths, and the share of cases it accepts. Computed.",
      "type": "object",
      "properties": {
        "process_tree": {
          "type": "string"
        },
        "cases_it_accepts": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        }
      },
      "required": [
        "process_tree",
        "cases_it_accepts"
      ],
      "additionalProperties": false
    },
    "decisions": {
      "description": "Every point where cases split between two or more next steps: the branches and their shares, the share a guess of the commonest branch would get right, the mined if-then rules, and whether the rules beat that guess by at least ten cases in a hundred. Mined and counted.",
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "at": {
            "type": "string"
          },
          "branches": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "to": {
                  "type": "string"
                },
                "cases": {
                  "type": "integer",
                  "minimum": 0
                },
                "share": {
                  "type": "number",
                  "minimum": 0,
                  "maximum": 1
                }
              },
              "required": [
                "to",
                "cases",
                "share"
              ],
              "additionalProperties": false
            }
          },
          "baseline_share": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "rules": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "when": {
                  "type": "array",
                  "items": {
                    "$ref": "#/definitions/plain"
                  }
                },
                "then": {
                  "type": "string"
                },
                "cases": {
                  "type": "integer",
                  "minimum": 0
                },
                "holds": {
                  "type": "number",
                  "minimum": 0,
                  "maximum": 1
                },
                "evidence": {
                  "$ref": "#/definitions/evidence"
                }
              },
              "required": [
                "id",
                "when",
                "then",
                "cases",
                "holds",
                "evidence"
              ],
              "additionalProperties": false
            }
          },
          "explained": {
            "type": "boolean"
          },
          "evidence": {
            "$ref": "#/definitions/evidence"
          }
        },
        "required": [
          "id",
          "at",
          "branches",
          "baseline_share",
          "rules",
          "explained",
          "evidence"
        ],
        "additionalProperties": false
      }
    },
    "sequence_rules": {
      "description": "Ordering rules that almost always hold, each with the share of cases where it holds. Mined, then counted over the paths.",
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "type": {
            "enum": [
              "precedence",
              "response",
              "at_most_once",
              "other"
            ]
          },
          "statement": {
            "type": "string"
          },
          "activities": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/plain"
            }
          },
          "holds": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "evidence": {
            "$ref": "#/definitions/evidence"
          }
        },
        "required": [
          "id",
          "type",
          "statement",
          "activities",
          "holds",
          "evidence"
        ],
        "additionalProperties": false
      }
    },
    "exceptions": {
      "description": "What goes off the normal path: repeated, skipped and out-of-order steps, rare activities and failed endings, each with its cases, the trigger if the data shows one, and how the case continues. Counted; trigger and handling are read from the data by the AI.",
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "trigger": {
            "type": "string"
          },
          "detected_by": {
            "type": "string"
          },
          "handling": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/plain"
            }
          },
          "cases": {
            "type": "integer",
            "minimum": 0
          },
          "evidence": {
            "$ref": "#/definitions/evidence"
          }
        },
        "required": [
          "id",
          "name",
          "trigger",
          "detected_by",
          "handling",
          "cases",
          "evidence"
        ],
        "additionalProperties": false
      }
    },
    "escalations": {
      "description": "Steps that appear mainly after a long wait or a failed attempt. Inferred: the data shows what happened, not what a written policy says.",
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "from": {
            "type": "string"
          },
          "to": {
            "type": "string"
          },
          "trigger": {
            "type": "string"
          },
          "evidence": {
            "$ref": "#/definitions/evidence"
          }
        },
        "required": [
          "id",
          "from",
          "to",
          "trigger",
          "evidence"
        ],
        "additionalProperties": false
      }
    },
    "policies": {
      "description": "Service levels and other limits most cases stay inside, with the limit in hours and the share that meets it. Inferred from the timings, never read from a policy document.",
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "kind": {
            "enum": [
              "service_level",
              "timing",
              "sequence",
              "separation"
            ]
          },
          "statement": {
            "type": "string"
          },
          "threshold_hours": {
            "type": "number",
            "minimum": 0
          },
          "share_met": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "evidence": {
            "$ref": "#/definitions/evidence"
          }
        },
        "required": [
          "id",
          "kind",
          "statement",
          "threshold_hours",
          "share_met",
          "evidence"
        ],
        "additionalProperties": false
      }
    },
    "roles": {
      "description": "Which roles perform which activities, when the log has a resource, user, team or role attribute. Counted. Empty when the log has none.",
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "attribute": {
            "type": "string"
          },
          "activities": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/plain"
            }
          },
          "cases": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "id",
          "name",
          "attribute",
          "activities",
          "cases"
        ],
        "additionalProperties": false
      }
    },
    "object_types": {
      "description": "The object types of an object-centric log, with their counts and the activities that touch each. Counted. Empty for a classic log.",
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "count": {
            "type": "integer",
            "minimum": 0
          },
          "activities": {
            "type": "array",
            "items": {
              "$ref": "#/definitions/plain"
            }
          }
        },
        "required": [
          "id",
          "name",
          "count",
          "activities"
        ],
        "additionalProperties": false
      }
    },
    "object_relations": {
      "description": "How the object types relate, with counts. Counted. Empty for a classic log.",
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "from_type": {
            "type": "string"
          },
          "to_type": {
            "type": "string"
          },
          "qualifier": {
            "type": "string"
          },
          "count": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "from_type",
          "to_type",
          "qualifier",
          "count"
        ],
        "additionalProperties": false
      }
    },
    "evidence_levels": {
      "description": "The five strength labels, each defined once in words, as used by every evidence object in this document.",
      "type": "object",
      "properties": {
        "counted": {
          "type": "string"
        },
        "strong": {
          "type": "string"
        },
        "moderate": {
          "type": "string"
        },
        "weak": {
          "type": "string"
        },
        "hypothesis": {
          "type": "string"
        }
      },
      "required": [
        "counted",
        "strong",
        "moderate",
        "weak",
        "hypothesis"
      ],
      "additionalProperties": false
    },
    "assumptions": {
      "description": "What was decided from the data before the work started, and everything that could not be measured or was left off. Text, or objects of the writer's own shape.",
      "type": "array",
      "items": {
        "$ref": "#/definitions/plain"
      }
    },
    "open_questions": {
      "description": "What a reader should look into, each with the evidence that raised it. No recommendations. Text, or objects of the writer's own shape.",
      "type": "array",
      "items": {
        "$ref": "#/definitions/plain"
      }
    }
  },
  "required": [
    "schema",
    "schema_version",
    "source",
    "process",
    "success_criteria",
    "outcomes",
    "stages",
    "nodes",
    "edges",
    "variants",
    "model",
    "decisions",
    "sequence_rules",
    "exceptions",
    "escalations",
    "policies",
    "roles",
    "object_types",
    "object_relations",
    "evidence_levels",
    "assumptions",
    "open_questions"
  ],
  "additionalProperties": false,
  "definitions": {
    "evidence": {
      "description": "The evidence one element rests on: how many cases it rests on, out of how many it could apply to, the share where it holds, one strength label, and how it was measured. The same object everywhere it appears.",
      "type": "object",
      "properties": {
        "cases": {
          "type": "integer",
          "minimum": 0
        },
        "of_cases": {
          "type": "integer",
          "minimum": 0
        },
        "share": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        },
        "strength": {
          "enum": [
            "counted",
            "strong",
            "moderate",
            "weak",
            "hypothesis"
          ]
        },
        "method": {
          "type": "string"
        }
      },
      "required": [
        "cases",
        "of_cases",
        "share",
        "strength",
        "method"
      ],
      "additionalProperties": false
    },
    "plain": {
      "description": "Any plain value: text, a number, true or false, a list or an object of plain values. Never null.",
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "number"
        },
        {
          "type": "boolean"
        },
        {
          "type": "array",
          "items": {
            "$ref": "#/definitions/plain"
          }
        },
        {
          "type": "object",
          "additionalProperties": {
            "$ref": "#/definitions/plain"
          }
        }
      ]
    }
  }
}
