memstead-schema 0.2.0

Schema types for Memstead — entity definitions, vocabulary, and validation rules.
Documentation
# yaml-language-server: $schema=../../generated/schema-manifest.schema.json

# ─────────────────────────────────────────────────────────────────────────────
# Recipe schema — fully commented example of a custom memstead schema.
#
# How to use:
#   1. Copy this directory into the workspace-level schemas dir
#      (schemas_dir in .memstead/workspace.toml, conventionally
#      <workspace>/schemas/recipe/)
#   2. Restart the MCP server so the new schema is picked up
#   3. In any mem's .memstead/config.json, set   "schema": "recipe@0.1.0"
#   4. Create entities with entity_type "recipe" or "ingredient"
#
# A schema is a package. It bundles every type definition, the full
# relationship vocabulary, and the LLM-facing documentation an agent needs
# to build a graph correctly. This file (schema.yaml) is the manifest.
# Each type gets its own file under types/.
# ─────────────────────────────────────────────────────────────────────────────

# Schema identity — both fields are pinned exactly by consuming mems.
# Never "latest", never a range. Bump version when any shape or semantics
# changes; external mems keep working against the old version.
name: recipe
version: 0.1.0

# description — required. Agents consuming the schema see this first.
# State the domain and what kinds of entities live here.
description: |
  Cooking recipes plus the ingredients they reference. Scoped to home-
  cooking workflows — not industrial food production, not nutrition
  databases.

# when_to_use — required. Teaches the agent WHEN to pick this schema
# versus authoring a different one. Contrast against neighbours.
when_to_use: |
  Use for personal recipe collections, cookbook authoring, or meal-
  planning knowledge graphs. Pick a different schema when you need
  nutrition analysis (per-100g macros, allergens), supplier pricing,
  or restaurant-scale production planning — those domains need
  vocabulary this schema deliberately does not carry.

# system_message — encouraged. Injected into MCP tool contexts whenever
# an agent works with this schema. Tell the agent the invariants of the
# domain and what "good" looks like.
system_message: |
  You are working in a cooking-recipe knowledge graph. Two entity types:
  recipe (instructions + ingredient list) and ingredient (pantry item
  plus substitution rules).

  Always link a recipe to its ingredients via CONTAINS, never via
  REFERENCES. When a recipe variant exists, use DERIVED_FROM so the
  lineage is explicit. Use SUBSTITUTES_FOR on ingredient pairs only —
  not on recipes.

# types — list of type names. Every name must match a file in types/
# (recipe.yaml, ingredient.yaml) and the name field inside that file.
# The loader cross-checks all three.
types:
  - recipe
  - ingredient

# relationships — the vocabulary of edges any entity in this schema may
# use. An edge using a relationship not listed here is:
#   strict mode → rejected at create/update/relate with a suggested match
#   open mode   → accepted, assigned _default weight, returned as warning
# Pick strict for stable domains, open while you're still discovering
# the vocabulary. Recipe is strict — the vocabulary is small and known.
relationships:
  mode: strict
  definitions:
    - name: CONTAINS
      description: |
        A recipe contains an ingredient. The ingredient is listed in the
        recipe's ingredient table.
      when_to_use: |
        Always for recipe→ingredient. Not for recipe→recipe composition
        (use DERIVED_FROM for variants, REFERENCES for "serve with").
      default_weight: 3.0

    - name: DERIVED_FROM
      description: |
        A recipe or ingredient is a variant of, or inspired by, another.
      when_to_use: |
        Use for recipe variants (vegan bolognese derived from classic
        bolognese) or ingredient substitutes that historically replaced
        another. Distinct from SUBSTITUTES_FOR which declares
        substitutability, not lineage.
      default_weight: 2.0

    - name: SUBSTITUTES_FOR
      description: |
        This ingredient can replace the target ingredient in recipes,
        possibly with caveats described in the source's body.
      when_to_use: |
        Only ingredient→ingredient. Read from the caller's side —
        "soy_sauce SUBSTITUTES_FOR tamari" means soy sauce can stand
        in for tamari.
      default_weight: 1.5

    - name: PART_OF
      description: |
        Structural containment — typically sub-recipes that are part of
        a larger recipe (pie_crust PART_OF apple_pie).
      when_to_use: |
        Use when the child would be meaningless or lost without the
        parent. If the child could stand alone as a recipe someone
        would cook independently, prefer REFERENCES instead.
      default_weight: 3.0

    - name: REFERENCES
      description: |
        Soft reference — "serve with", "pairs well with", "see also".
      when_to_use: |
        Auto-emitted from inline wiki-links; rarely authored by hand.
        Use over PART_OF when the target stands alone.
      default_weight: 0.5

    - name: _default
      description: |
        Fallback weight for any relationship not otherwise declared.
        Required by the engine; do not remove.
      default_weight: 1.0

# community — Louvain algorithm parameters for cluster detection on the
# graph. Defaults are sensible for most schemas.
# resolution: higher = more, smaller clusters.
# seed:       deterministic partitioning across runs.
community:
  resolution: 1.0
  seed: 42