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": "Not in the pantry, and assumed present anyway because it is on the staples list. An assumption, so it is named on the page rather than folded silently into the coverage."
    },
    "missing": {
      "type": "token",
      "description": "Not in the pantry and not a staple. 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"
          ]
        },
        "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."
    },
    "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, staples 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
bafyreihs3kq4r2zbpjwtzyltidjnycilutoqk4klkll3kjz4e367veaemu
Indexed At
2026-08-25 08:11 UTC
AT-URI
at://did:plc:vd7yvfuocu3xr54lnszirlgz/com.atproto.lexicon.schema/ink.igav.whatmealtodo.defs

Version History (2 versions)

Lexicon Garden

@