{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/hoshin-app/json-schema/hoshin-app-element-updated-schema.json",
  "title": "ElementUpdated",
  "x-generated": "2026-11-11",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/hoshin-app-openapi.json#/components/schemas/ElementUpdated",
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "matrixId": {
      "type": "string",
      "format": "uuid"
    },
    "quadrant": {
      "type": "string",
      "enum": [
        "north",
        "east",
        "south",
        "west"
      ],
      "description": "Role of the element, not its place on the drawing: north = breakthrough objectives (3-5 year vision), east = annual objectives, south = initiatives, west = KPIs. A matrix drawn with the vision at the bottom uses the same values."
    },
    "position": {
      "type": "integer"
    },
    "title": {
      "type": "string"
    },
    "description": {
      "type": [
        "string",
        "null"
      ]
    },
    "status": {
      "type": "string",
      "enum": [
        "draft",
        "active",
        "completed",
        "cancelled"
      ]
    },
    "ownerId": {
      "type": [
        "string",
        "null"
      ],
      "format": "uuid"
    },
    "ownerName": {
      "type": [
        "string",
        "null"
      ]
    },
    "targetValue": {
      "type": [
        "string",
        "null"
      ]
    },
    "currentValue": {
      "type": [
        "string",
        "null"
      ]
    },
    "unit": {
      "type": [
        "string",
        "null"
      ]
    },
    "indicatorType": {
      "type": [
        "string",
        "null"
      ],
      "enum": [
        "result",
        "performance",
        null
      ]
    },
    "dueDate": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time"
    },
    "completedAt": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time"
    },
    "color": {
      "type": [
        "string",
        "null"
      ]
    },
    "icon": {
      "type": [
        "string",
        "null"
      ]
    },
    "externalRef": {
      "type": [
        "string",
        "null"
      ]
    },
    "links": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string"
          },
          "ref": {
            "type": "string"
          }
        },
        "required": [
          "label",
          "ref"
        ]
      },
      "description": "Links to third-party tools: a free label and a free reference (URL, ticket or project number, path)."
    },
    "parentElementId": {
      "type": [
        "string",
        "null"
      ],
      "format": "uuid"
    },
    "progress": {
      "type": [
        "integer",
        "null"
      ],
      "description": "Last progress reported (0-100); null on a KPI or before any update."
    },
    "visibility": {
      "type": "string",
      "enum": [
        "shared",
        "internal"
      ]
    },
    "sheet": {
      "type": "object",
      "properties": {
        "sponsor": {
          "type": "string",
          "minLength": 1,
          "maxLength": 100,
          "description": "Sponsor, when not the owner of the initiative."
        },
        "why": {
          "type": "string",
          "minLength": 1,
          "maxLength": 2000,
          "description": "The problem it addresses and the annual objective it serves."
        },
        "expectedResult": {
          "type": "string",
          "minLength": 1,
          "maxLength": 1000,
          "description": "What \"done\" means."
        },
        "measuredBy": {
          "type": "string",
          "format": "uuid",
          "description": "The KPI (west element of the same matrix) that measures the result."
        },
        "milestones": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "title": {
                "type": "string",
                "minLength": 1,
                "maxLength": 200
              },
              "date": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date",
                "description": "YYYY-MM-DD"
              },
              "status": {
                "type": "string",
                "enum": [
                  "planned",
                  "done",
                  "late"
                ],
                "description": "\"planned\", \"done\" (reached) or \"late\"."
              }
            },
            "required": [
              "title",
              "status"
            ]
          },
          "maxItems": 8,
          "description": "3 to 6 dated milestones, 8 at most."
        },
        "nextAction": {
          "type": "object",
          "properties": {
            "title": {
              "type": "string",
              "minLength": 1,
              "maxLength": 300
            },
            "owner": {
              "type": [
                "string",
                "null"
              ],
              "minLength": 1,
              "maxLength": 100,
              "description": "Who does it, as people name them."
            },
            "due": {
              "type": [
                "string",
                "null"
              ],
              "format": "date",
              "description": "YYYY-MM-DD"
            }
          },
          "required": [
            "title"
          ]
        },
        "health": {
          "type": "string",
          "enum": [
            "green",
            "amber",
            "red"
          ],
          "description": "Weather of the initiative, updated at each review. Requires healthNote."
        },
        "healthNote": {
          "type": "string",
          "minLength": 1,
          "maxLength": 500,
          "description": "One sentence that justifies the weather."
        },
        "blockers": {
          "type": "string",
          "minLength": 1,
          "maxLength": 2000,
          "description": "Risks, and what needs an arbitration or a decision of the committee."
        },
        "resources": {
          "type": "string",
          "minLength": 1,
          "maxLength": 1000,
          "description": "Budget, time, hires needed."
        },
        "healthAt": {
          "type": "string",
          "description": "When the weather was last set (ISO datetime)."
        }
      },
      "description": "Initiatives (south) only, else empty: the sheet a committee reads in two minutes."
    },
    "kpiDefinition": {
      "type": "object",
      "properties": {
        "formula": {
          "type": "string",
          "minLength": 1,
          "maxLength": 1000,
          "description": "How the value is computed, e.g. \"active accounts / signed accounts, at month end\"."
        },
        "sourceSystem": {
          "type": "string",
          "minLength": 1,
          "maxLength": 100,
          "description": "The system the value is read in (e.g. \"HubSpot\", \"Pennylane\")."
        },
        "sourceRef": {
          "type": "string",
          "minLength": 1,
          "maxLength": 500,
          "description": "Where in it: a report, a saved query, a URL."
        },
        "dataOwner": {
          "type": "string",
          "minLength": 1,
          "maxLength": 100,
          "description": "Who answers for the number."
        },
        "frequency": {
          "type": "string",
          "enum": [
            "monthly",
            "quarterly"
          ],
          "description": "How often a reading is due."
        }
      },
      "description": "KPIs (west) only, else empty: how the value is computed and where it is read."
    },
    "createdAt": {
      "type": "string",
      "format": "date-time"
    },
    "updatedAt": {
      "type": "string",
      "format": "date-time"
    },
    "droppedCorrelations": {
      "type": "integer",
      "description": "Correlations removed because a change of quadrant left them non-adjacent."
    }
  },
  "required": [
    "id",
    "matrixId",
    "quadrant",
    "position",
    "title",
    "description",
    "status",
    "ownerId",
    "ownerName",
    "targetValue",
    "currentValue",
    "unit",
    "indicatorType",
    "dueDate",
    "completedAt",
    "color",
    "icon",
    "externalRef",
    "links",
    "parentElementId",
    "progress",
    "visibility",
    "sheet",
    "kpiDefinition",
    "createdAt",
    "updatedAt"
  ]
}