{
  "id": "dbt/jaffle-shop-status",
  "slug": "jaffle-shop-status",
  "name": "Jaffle Shop, worked: what `orders.status` means",
  "tagline": "dbt Labs' sample project, with its five-value status column annotated so an agent looks it up instead of guessing. Every field is on the page.",
  "description": "A worked instance of the agent-grounding recipe on jaffle-shop-classic, the dbt Labs sample project most analytics engineers run first. Its docs tell a human what the five `orders.status` values mean. They do not tell an agent that `paid` and `cancelled` do not exist, that `shipped` is not revenue, or that `stg_payments` has no status column at all. This recipe fills exactly that layer (meaningNote, commonMistake, doNotUseFor, permitted values and an owner), then shows the SQL an agent writes before and after it can read them. Import the same manifest into your own workspace and fill the same fields.",
  "url": "https://coremodels.io/recipe/jaffle-shop-status",
  "json": "https://coremodels.io/recipe/jaffle-shop-status.json",
  "markdown": "https://coremodels.io/recipe/jaffle-shop-status.md",
  "status": null,
  "connectors": [
    {
      "slug": "dbt",
      "name": "dbt",
      "url": "https://coremodels.io/connector/dbt",
      "recipeUrl": "https://coremodels.io/connector/dbt/recipe/jaffle-shop-status",
      "capabilities": [
        "import"
      ]
    }
  ],
  "steps": [
    "Run `dbt parse` on jaffle-shop-classic and import target/manifest.json; each accepted_values list, orders.status included, becomes a governed vocabulary.",
    "Fill meaningNote, commonMistake and doNotUseFor on the columns an agent gets wrong. The annotated set is below.",
    "Point your assistant at the read-only endpoint and ask: what was completed revenue last month?"
  ],
  "start": {
    "label": "Start with this recipe →",
    "href": "https://go.coremodels.io/app/new/dbt/jaffle-shop-status",
    "note": "No warehouse credential. No dbt Cloud token. Read-only."
  },
  "stories": [],
  "guides": [
    {
      "slug": "h5-agents",
      "title": "The Fourth Option for a Column Named status",
      "summary": "This is no longer a hypothetical audience. dbt Labs' [2026 State of Analytics Engineering](https://www.getdbt.com/resources/state-of-analytics-engineering-2026) (n=363) reports **72% of teams prioritizing AI-assisted coding** and **71% concerned about incorrect data reaching stakeholders** — the same teams, describing both halves of the problem below.",
      "audience": "strategy",
      "url": "https://coremodels.io/connector/dbt/h5-agents"
    },
    {
      "slug": "t6-agent-grounding",
      "title": "Grounding an Agent in Your dbt Project: What It Reads, and What Changes",
      "summary": "An agent pointed at your warehouse can already write SQL. The question is what it knows about the columns it writes against, and the honest answer is: the names, the types, and whatever free text happens to be in a description. Everything else it infers.",
      "audience": "engineering",
      "url": "https://coremodels.io/connector/dbt/t6-agent-grounding"
    },
    {
      "slug": "t3-mcp",
      "title": "Four Tools and a Ledger: dbt Contracts from an Agent's Seat",
      "summary": "\"Generate the contracts for `stg_orders` and `stg_customers`, and tell me if anything won't apply cleanly.\" That sentence is an afternoon of dbt property-file maintenance, and an agent connected to CoreModels over MCP can answer it with real tool calls instead of plausible-looking YAML. Four vendor integration tools give the agent the same governance surface a human gets over HTTP: the same role checks, the same read-only guarantees, and the same honest ledger of what could not be represented.",
      "audience": "engineering",
      "url": "https://coremodels.io/connector/dbt/t3-mcp"
    }
  ],
  "agentInstructions": "Before you assert what a Jaffle Shop column means, allows, or is used for, read its entry in columns. If it has permittedValues, do not invent another value. If it has doNotUseFor, obey it. If you cannot find the column, say so; do not infer it from the name.",
  "worked": {
    "title": "Jaffle Shop · orders.status",
    "source": {
      "project": "jaffle-shop-classic",
      "publisher": "dbt Labs",
      "projectUrl": "https://github.com/dbt-labs/jaffle-shop-classic",
      "schemaUrl": "https://github.com/dbt-labs/jaffle-shop-classic/blob/main/models/schema.yml",
      "docsUrl": "https://github.com/dbt-labs/jaffle-shop-classic/blob/main/models/docs.md",
      "license": "Apache-2.0",
      "licenseUrl": "https://github.com/dbt-labs/jaffle-shop-classic/blob/main/LICENSE",
      "attribution": "Jaffle Shop is dbt Labs' sample project jaffle-shop-classic, licensed Apache-2.0. The models, the columns, the accepted_values lists and the five status descriptions are theirs (models/schema.yml, models/docs.md). The annotations on this page (meaningNote, commonMistake, doNotUseFor, owners) are CoreModels example content, not part of the upstream project."
    },
    "people": [
      {
        "name": "Maya Chen",
        "role": "Analytics engineer",
        "synthetic": true
      },
      {
        "name": "Jordan Hale",
        "role": "Finance lead",
        "synthetic": true
      }
    ],
    "peopleNote": "Maya Chen and Jordan Hale are example people, invented for this recipe. They are not customers or staff.",
    "models": [
      {
        "name": "customers",
        "kind": "mart",
        "description": "One row per customer, with derived facts from that customer's orders and payments."
      },
      {
        "name": "orders",
        "kind": "mart",
        "description": "One row per order, with payment amounts by method. Carries status."
      },
      {
        "name": "stg_orders",
        "kind": "staging",
        "description": "Cleaned orders from the raw_orders seed. Carries the same status column and the same accepted_values test."
      },
      {
        "name": "stg_payments",
        "kind": "staging",
        "description": "Cleaned payments from the raw_payments seed: payment_method and amount. No status column."
      }
    ],
    "vocabularies": [
      {
        "name": "orders_status",
        "source": "accepted_values on orders.status and stg_orders.status; descriptions from the orders_status docs block in models/docs.md",
        "values": [
          {
            "value": "placed",
            "description": "The order has been placed but has not yet left the warehouse."
          },
          {
            "value": "shipped",
            "description": "The order has been shipped to the customer and is currently in transit."
          },
          {
            "value": "completed",
            "description": "The order has been received by the customer."
          },
          {
            "value": "return_pending",
            "description": "The customer has indicated that they would like to return the order, but it has not yet been received at the warehouse."
          },
          {
            "value": "returned",
            "description": "The order has been returned by the customer and received at the warehouse."
          }
        ]
      },
      {
        "name": "payment_method",
        "source": "accepted_values on stg_payments.payment_method",
        "values": [
          {
            "value": "credit_card",
            "description": "Paid by credit card."
          },
          {
            "value": "coupon",
            "description": "Paid by coupon."
          },
          {
            "value": "bank_transfer",
            "description": "Paid by bank transfer."
          },
          {
            "value": "gift_card",
            "description": "Paid by gift card."
          }
        ]
      }
    ],
    "heroColumn": "orders.status",
    "columns": [
      {
        "id": "orders.status",
        "model": "orders",
        "name": "status",
        "type": "string",
        "owner": "Jordan Hale",
        "ownerRole": "Finance lead",
        "steward": "Maya Chen",
        "stewardRole": "Analytics engineer",
        "vocabulary": "orders_status",
        "permittedValues": [
          "placed",
          "shipped",
          "completed",
          "return_pending",
          "returned"
        ],
        "definition": "Fulfillment state of a single order. Five values, mutually exclusive. The values and their descriptions come from the orders_status docs block in jaffle-shop-classic.",
        "meaningNote": "This is the fulfillment state of one order, not a customer lifecycle flag and not a payment result. Only completed means the customer received the goods. placed and shipped are open. return_pending and returned come after the fact: they are not kinds of open and not kinds of successful. There is no cancelled, pending, paid, active or failed value in this column.",
        "commonMistake": "Inventing values the column does not have (pending, cancelled, active, paid, success). Treating shipped plus completed as successful orders. Reading status as a property of the customer rather than the order. Looking for a status on payments: stg_payments has none in this project.",
        "doNotUseFor": "Revenue on its own (filter amount where status = 'completed'). Active-customer counts. Payment success or failure. Inventory on hand. Any query that IN-lists values you did not look up here.",
        "agentGuidance": "Before writing SQL against orders.status, read permittedValues. If the question says revenue, completed or sold, filter status = 'completed'. If it says open or in flight, use placed or shipped. If it says returns, use return_pending or returned. Never invent a sixth value.",
        "source": {
          "file": "models/schema.yml",
          "test": "accepted_values",
          "docsBlock": "orders_status"
        }
      },
      {
        "id": "stg_orders.status",
        "model": "stg_orders",
        "name": "status",
        "type": "string",
        "owner": "Maya Chen",
        "ownerRole": "Analytics engineer",
        "vocabulary": "orders_status",
        "permittedValues": [
          "placed",
          "shipped",
          "completed",
          "return_pending",
          "returned"
        ],
        "definition": "The staging copy of the same field. Same vocabulary as orders.status.",
        "meaningNote": "Identical permitted values to orders.status. Prefer the mart column in analyst questions unless the question is about the staging model itself.",
        "commonMistake": "Declaring a different accepted_values list here than on orders.status. Both tests can pass. That is how two definitions of one column survive in a dbt project.",
        "doNotUseFor": "A second, private meaning of status. If staging and mart disagree, that is drift, not a new definition.",
        "source": {
          "file": "models/staging/schema.yml",
          "test": "accepted_values"
        }
      },
      {
        "id": "orders.amount",
        "model": "orders",
        "name": "amount",
        "type": "numeric",
        "unit": "AUD",
        "owner": "Jordan Hale",
        "ownerRole": "Finance lead",
        "definition": "Total amount of the order in Australian dollars: the sum of the credit_card, coupon, bank_transfer and gift_card payment amounts.",
        "meaningNote": "Present on every order whatever its status. It is not revenue. Completed revenue is sum(amount) where status = 'completed'. The raw_payments seed stores cents; by the time it reaches this column it is dollars.",
        "commonMistake": "sum(amount) across all statuses, labelled revenue. Assuming USD. Adding raw_payments.amount (cents) to it. Treating coupon_amount as a discount rather than a payment method.",
        "doNotUseFor": "Completed revenue without a status filter. USD reporting. Margin: there is no cost column in this project.",
        "source": {
          "file": "models/schema.yml"
        }
      },
      {
        "id": "customers.customer_lifetime_value",
        "model": "customers",
        "name": "customer_lifetime_value",
        "type": "numeric",
        "unit": "AUD",
        "owner": "Jordan Hale",
        "ownerRole": "Finance lead",
        "definition": "Lifetime sum of payments for this customer's orders, all statuses. customers.sql emits this column as customer_lifetime_value; models/schema.yml documents the same figure under the name total_order_amount, which the model does not produce.",
        "meaningNote": "Lifetime gross payments, not completed-only value and not current-period revenue, whatever the name suggests.",
        "commonMistake": "Querying total_order_amount: it is documented in schema.yml but is not a column of the built table. Calling this figure what the customer paid and kept: it includes placed, shipped, return_pending and returned orders.",
        "doNotUseFor": "Period revenue. Completed-only customer value. Churn or active-customer definitions.",
        "source": {
          "file": "models/customers.sql"
        }
      },
      {
        "id": "customers.number_of_orders",
        "model": "customers",
        "name": "number_of_orders",
        "type": "integer",
        "owner": "Maya Chen",
        "ownerRole": "Analytics engineer",
        "definition": "Count of the orders this customer has placed, all statuses.",
        "meaningNote": "Includes return_pending and returned orders. A customer with one placed order and one returned order has number_of_orders = 2.",
        "commonMistake": "Using it as a count of completed purchases, or as a proxy for active.",
        "doNotUseFor": "Completed-order counts. Active-customer flags.",
        "source": {
          "file": "models/schema.yml"
        }
      },
      {
        "id": "customers.first_name",
        "model": "customers",
        "name": "first_name",
        "type": "string",
        "pii": true,
        "owner": "Maya Chen",
        "ownerRole": "Analytics engineer",
        "definition": "Customer's first name. Marked PII in the upstream schema.yml.",
        "meaningNote": "Personal data. The seed values are fictional, which is the only reason this example shows the column at all.",
        "commonMistake": "Echoing names into agent logs, eval traces or answers as if they were a dimension.",
        "doNotUseFor": "Joins, aggregations, or anything an agent might print. Use customer_id.",
        "source": {
          "file": "models/schema.yml"
        }
      },
      {
        "id": "customers.last_name",
        "model": "customers",
        "name": "last_name",
        "type": "string",
        "pii": true,
        "owner": "Maya Chen",
        "ownerRole": "Analytics engineer",
        "definition": "Customer's last name. Marked PII in the upstream schema.yml.",
        "meaningNote": "Personal data. The seed values are fictional.",
        "commonMistake": "Same as first_name.",
        "doNotUseFor": "Joins, aggregations, or anything an agent might print. Use customer_id.",
        "source": {
          "file": "models/schema.yml"
        }
      },
      {
        "id": "stg_payments.payment_method",
        "model": "stg_payments",
        "name": "payment_method",
        "type": "string",
        "owner": "Maya Chen",
        "ownerRole": "Analytics engineer",
        "vocabulary": "payment_method",
        "permittedValues": [
          "credit_card",
          "coupon",
          "bank_transfer",
          "gift_card"
        ],
        "definition": "How this payment was tendered. One row per payment; an order can have several.",
        "meaningNote": "coupon is a payment method in this project, not a discount. There is no payment status column in jaffle-shop-classic.",
        "commonMistake": "Inventing cash or paypal. Treating coupon as a markdown against amount. Looking for a payments status column: it does not exist here.",
        "doNotUseFor": "Order fulfillment state (that is orders.status). Discount analysis. A second status vocabulary.",
        "source": {
          "file": "models/staging/schema.yml",
          "test": "accepted_values"
        }
      },
      {
        "id": "stg_payments.amount",
        "model": "stg_payments",
        "name": "amount",
        "type": "numeric",
        "unit": "AUD",
        "owner": "Maya Chen",
        "ownerRole": "Analytics engineer",
        "definition": "Payment amount in dollars. The raw_payments seed stores cents; stg_payments.sql divides by 100.",
        "meaningNote": "Already converted: this column and orders.amount are both dollars. Only the raw_payments seed is in cents.",
        "commonMistake": "Dividing by 100 a second time. Reading the raw_payments seed directly and summing cents as dollars.",
        "doNotUseFor": "Revenue on its own: join to orders and filter status = 'completed'. Mixing with raw_payments.amount without converting.",
        "source": {
          "file": "models/staging/stg_payments.sql"
        }
      }
    ],
    "eval": {
      "question": "What was completed revenue last month?",
      "whyThisQuestion": "A text-to-SQL assistant that cannot look the column up guesses a status list, and the guess is usually some mix of shipped, completed and paid.",
      "ungroundedSql": "select sum(amount) as revenue\nfrom orders\nwhere order_date >= date_trunc('month', current_date - interval '1 month')\n  and order_date < date_trunc('month', current_date)\n  and status in ('shipped', 'completed', 'paid');",
      "ungroundedErrors": [
        "paid is not a permitted value. It matches no rows, so the query runs cleanly and nobody learns the guess was wrong.",
        "shipped is not revenue: the customer has not received the goods.",
        "The currency is unstated. The column is AUD."
      ],
      "groundedSql": "select sum(amount) as completed_revenue_aud\nfrom orders\nwhere order_date >= date_trunc('month', current_date - interval '1 month')\n  and order_date < date_trunc('month', current_date)\n  and status = 'completed';",
      "groundedReason": "orders.status has five permitted values and no paid. Its doNotUseFor says revenue means filtering status = 'completed'. orders.amount says the unit is AUD."
    }
  },
  "mcp": {
    "endpoint": "https://go.coremodels.io/mcp",
    "readOnly": true,
    "docs": "https://library.schematica.io/mcp-server",
    "clientConfig": {
      "mcpServers": {
        "coremodels": {
          "url": "https://go.coremodels.io/mcp",
          "headers": {
            "Authorization": "Bearer <your CoreModels API key>"
          }
        }
      }
    },
    "claudeCode": "claude mcp add --transport http coremodels https://go.coremodels.io/mcp",
    "note": "Connect to your own workspace after importing the manifest. There is no public demo project."
  }
}
