{
  "$type": "com.atproto.lexicon.schema",
  "defs": {
    "main": {
      "description": "One append-only event on a plant's timeline. A single record type unifies what other journals split into status changes, activities, measurements, and notes — because they are all the same shape (a timestamped thing that happened to a plant) and the distinguishing detail is an open `kind` vocabulary. Stage transitions (kind \"stage\") are how lifecycle is tracked: the AppView reads the latest stage entry as the plant's current stage and the full set as its lifecycle history. Activities (watering, feeding, training, …) optionally carry structured `measurements`. Freeform observation is the `note` field — deliberately loose so growers can record measurements prose, LST details, and anything else without the schema being prescriptive. Photos are NOT embedded here; they are separate `org.cannadb.growPhoto` records that may link back to an entry. Publishing this record IS the claim — contextualized by the publisher DID at display time.",
      "key": "tid",
      "record": {
        "properties": {
          "createdAt": {
            "description": "Client-declared timestamp when this entry record was created.",
            "format": "datetime",
            "type": "string"
          },
          "grow": {
            "description": "Optional denormalized AT-URI reference to the plant's `org.cannadb.grow`. Lets the AppView assemble a whole-grow timeline and gate on the grow's `listed` preference without resolving every plant first. The plant ref is canonical; this is a cache for query efficiency and ref resilience.",
            "format": "at-uri",
            "type": "string"
          },
          "kind": {
            "description": "What kind of event this is. Open vocabulary — clients should accept unknown values and fall back to generic display, and may offer user-defined kinds. \"stage\" marks a lifecycle transition and is the one kind that gives `stage` meaning.",
            "knownValues": [
              "stage",
              "watering",
              "feeding",
              "note",
              "measurement",
              "training",
              "transplant",
              "topping",
              "defoliation",
              "flush",
              "pest",
              "disease",
              "treatment",
              "harvest"
            ],
            "type": "string"
          },
          "measurements": {
            "description": "Structured readings recorded with this event (height, pH, EC/PPM, runoff pH, water volume, …). Optional — most entries carry none. A feeding entry might carry pH and EC; a check-up entry might carry height. Mirrors how journaling tools attach measurements to an activity.",
            "items": {
              "ref": "#measurement",
              "type": "ref"
            },
            "type": "array"
          },
          "note": {
            "description": "Markdown-formatted free-form note — the catch-all for anything the structured fields don't capture (measurement context, LST/defoliation details, observations, photos commentary). Deliberately unstructured.",
            "maxGraphemes": 10000,
            "maxLength": 100000,
            "type": "string"
          },
          "occurredAt": {
            "description": "When the event actually happened, if different from `createdAt` (e.g., logging yesterday's feeding today). Consumers default to `createdAt` when absent. This is the field timelines sort on.",
            "format": "datetime",
            "type": "string"
          },
          "plant": {
            "description": "AT-URI reference to the `org.cannadb.plant` this event belongs to. (Consumers should validate the ref resolves to an `org.cannadb.plant` record.)",
            "format": "at-uri",
            "type": "string"
          },
          "stage": {
            "description": "The lifecycle stage this entry marks a transition into. Set on stage transitions (typically with `kind` \"stage\"). The AppView treats the most recent entry carrying a `stage` as the plant's current stage, and the full ordered set as its lifecycle history. Display ordering of stages is an AppView concern. Open vocabulary.",
            "knownValues": [
              "germinating",
              "seedling",
              "vegetative",
              "flowering",
              "drying",
              "curing",
              "harvested",
              "dead"
            ],
            "type": "string"
          }
        },
        "required": [
          "plant",
          "createdAt"
        ],
        "type": "object"
      },
      "type": "record"
    },
    "measurement": {
      "description": "A single structured reading. Both `metric` and `unit` are open vocabularies. `value` is a scaled integer in hundredths of `unit` (atproto has no float type), matching the scaled-integer convention used for cannabinoid percentages on `org.cannadb.strain`: pH 6.25 = 625 with unit \"ph\"; height 30.5 cm = 3050 with unit \"cm\"; EC 1.85 = 185 with unit \"mS_cm\".",
      "properties": {
        "metric": {
          "description": "What was measured. Open vocabulary — consumers accept unknown metrics and may offer user-defined ones.",
          "knownValues": [
            "height",
            "ph",
            "ec",
            "ppm",
            "tds",
            "runoff_ph",
            "water_volume",
            "temperature",
            "humidity",
            "pot_size"
          ],
          "type": "string"
        },
        "unit": {
          "description": "Unit of `value`. Open vocabulary; required to interpret the scaled integer. Consumers should accept unknown units and fall back to displaying the unit string as written.",
          "knownValues": [
            "cm",
            "in",
            "ph",
            "mS_cm",
            "ppm",
            "ml",
            "l",
            "gal",
            "celsius",
            "fahrenheit",
            "percent"
          ],
          "type": "string"
        },
        "value": {
          "description": "The measured value in hundredths of `unit` (e.g., 625 = 6.25). Scaled integer because atproto has no float type.",
          "type": "integer"
        }
      },
      "required": [
        "metric",
        "value"
      ],
      "type": "object"
    }
  },
  "id": "org.cannadb.growEntry",
  "lexicon": 1
}
