ink.igav.whatmealtodo.defs

kaur.igav.ink

{
  "id": "ink.igav.whatmealtodo.defs",
  "defs": {
    "head": {
      "type": "token",
      "description": "Matched on the head noun only — pantry 'flour' against recipe 'all-purpose flour'. Weaker than exact, and shown as such."
    },
    "exact": {
      "type": "token",
      "description": "The recipe's canonical ingredient equals a canonical name in the pantry."
    },
    "staple": {
      "type": "token",
      "description": "Something the kitchen always holds rather than happens to hold. As a pantryItem `kind`, that is what its owner asserted about it; as a match verdict, it is why the ingredient counted. Said out loud in both places rather than folded silently into the coverage, because 'you keep this around' is a weaker claim than 'you have this right now' and a reader is entitled to tell them apart."
    },
    "missing": {
      "type": "token",
      "description": "Neither held nor kept on hand. This is what a shopping list is made of."
    },
    "proposed": {
      "type": "token",
      "description": "The name was produced by the normalizer and accepted as offered."
    },
    "quantity": {
      "type": "object",
      "required": [
        "value"
      ],
      "properties": {
        "unit": {
          "type": "string",
          "maxLength": 32,
          "description": "Plain lowercase strings rather than tokens, and deliberately open. A person types what they have, and a vocabulary that refused 'punnet' would push the real value into the free text where nothing can read it. The known values are the ones the normalizer emits.",
          "knownValues": [
            "g",
            "kg",
            "ml",
            "l",
            "tsp",
            "tbsp",
            "cup",
            "oz",
            "lb",
            "clove",
            "can",
            "jar",
            "package",
            "piece",
            "slice",
            "stick",
            "pinch",
            "dash",
            "basket",
            "bunch",
            "handful",
            "sprig",
            "stalk",
            "head",
            "bag",
            "box",
            "bottle",
            "packet",
            "sachet",
            "envelope",
            "tin",
            "tub"
          ]
        },
        "value": {
          "type": "number",
          "minimum": 0
        }
      },
      "description": "How much of something there is. Optional wherever it appears: 'some flour' is a legitimate pantry entry, and a recipe that says 'a handful of parsley' has no number to give."
    },
    "unparsed": {
      "type": "token",
      "description": "The normalizer could not reduce the ingredient to a name, so no claim is made about it either way. Distinct from `missing`: one is an answer, the other is a failure to have one."
    },
    "corrected": {
      "type": "token",
      "description": "A person overrode the normalizer's proposal. Every one of these is a case the rules got wrong, which is why it is recorded rather than discarded."
    },
    "ingredient": {
      "type": "token",
      "description": "A pantry item the kitchen happens to hold — a stock level, and the kind that runs out. The default reading of a pantryItem with no `kind`."
    },
    "recipeView": {
      "type": "object",
      "required": [
        "uri",
        "cid",
        "author",
        "name",
        "indexedAt"
      ],
      "properties": {
        "cid": {
          "type": "string",
          "format": "cid"
        },
        "uri": {
          "type": "string",
          "format": "at-uri"
        },
        "name": {
          "type": "string",
          "maxLength": 255
        },
        "text": {
          "type": "string",
          "maxLength": 3000
        },
        "author": {
          "type": "string",
          "format": "did"
        },
        "indexedAt": {
          "type": "string",
          "format": "datetime",
          "description": "When this AppView indexed it. Says nothing about when it was written — that is the record's own createdAt."
        },
        "totalTime": {
          "type": "string",
          "format": "duration"
        },
        "recipeCuisine": {
          "type": "string"
        },
        "recipeCategory": {
          "type": "string"
        },
        "suitableForDiet": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "description": "A recipe as this AppView holds it. A projection of exchange.recipe.recipe, not a copy: only the fields a suggestion needs."
    },
    "suggestion": {
      "type": "object",
      "required": [
        "recipe",
        "ingredients",
        "coverage",
        "missing"
      ],
      "properties": {
        "recipe": {
          "ref": "#recipeView",
          "type": "ref"
        },
        "missing": {
          "type": "array",
          "items": {
            "type": "string",
            "maxLength": 100
          },
          "description": "The canonical names with verdict `missing`. Empty means cook now."
        },
        "coverage": {
          "type": "number",
          "maximum": 1,
          "minimum": 0,
          "description": "Matched ingredients over total, items kept on hand counted as matched, unparsed ingredients counted against — an ingredient we could not read is not an ingredient we have."
        },
        "unreadable": {
          "type": "integer",
          "minimum": 0,
          "description": "How many ingredients came back unparsed. Surfaced next to the result rather than hidden, so a suspiciously poor match is legible as a normalizer failure instead of a missing ingredient."
        },
        "ingredients": {
          "type": "array",
          "items": {
            "ref": "#ingredientMatch",
            "type": "ref"
          }
        }
      },
      "description": "One recipe measured against one pantry."
    },
    "ingredientMatch": {
      "type": "object",
      "required": [
        "raw",
        "verdict"
      ],
      "properties": {
        "raw": {
          "type": "string",
          "maxLength": 500,
          "description": "The ingredient exactly as the recipe wrote it."
        },
        "verdict": {
          "type": "string",
          "knownValues": [
            "ink.igav.whatmealtodo.defs#exact",
            "ink.igav.whatmealtodo.defs#head",
            "ink.igav.whatmealtodo.defs#staple",
            "ink.igav.whatmealtodo.defs#missing",
            "ink.igav.whatmealtodo.defs#unparsed"
          ]
        },
        "canonical": {
          "type": "string",
          "maxLength": 100,
          "description": "What the normalizer reduced it to. Absent when the verdict is unparsed."
        }
      },
      "description": "One recipe ingredient, and what became of it. Carried per ingredient rather than summarised, because a coverage number with no account of how it was reached is indistinguishable from a bug."
    }
  },
  "$type": "com.atproto.lexicon.schema",
  "lexicon": 1
}

Validate Record

Validate a record against ink.igav.whatmealtodo.defs

Validation Options
Treat any remaining unresolved references as valid

Metadata

DID
did:plc:vd7yvfuocu3xr54lnszirlgz
CID
bafyreiht44pnuolpt5ygzqpyfr6zsoxk3ujkhnkby7grm2t4wxawyazhve
Indexed At
2026-08-27 09:35 UTC
AT-URI
at://did:plc:vd7yvfuocu3xr54lnszirlgz/com.atproto.lexicon.schema/ink.igav.whatmealtodo.defs

Version History (2 versions)

Lexicon Garden

@